Metadata-Version: 2.4
Name: zentroq
Version: 0.5.1
Summary: ZentroQ SDK — certify quantum software releases from your Qrisp/Qiskit pipeline (a SecQDevOps MOD-08 service).
Author: SecQDevOps / ZentroQ
License: Apache-2.0
Project-URL: Homepage, https://certify.zortenet.eu
Keywords: quantum,qiskit,qrisp,compliance,certification,cra,qbom,sbom
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: quantum
Requires-Dist: qiskit<3,>=2.0; extra == "quantum"
Requires-Dist: qiskit-qasm3-import>=0.5; extra == "quantum"
Provides-Extra: qrisp
Requires-Dist: qrisp<1,>=0.8; extra == "qrisp"
Provides-Extra: cirq
Requires-Dist: cirq-core<2,>=1.4; extra == "cirq"
Provides-Extra: braket
Requires-Dist: amazon-braket-sdk<2,>=1.80; extra == "braket"
Provides-Extra: pennylane
Requires-Dist: pennylane<1,>=0.41; extra == "pennylane"
Provides-Extra: cudaq
Requires-Dist: cudaq<1,>=0.9; extra == "cudaq"
Provides-Extra: ibm
Requires-Dist: qiskit-ibm-runtime>=0.20; extra == "ibm"
Provides-Extra: verify
Requires-Dist: mqt.qcec>=3.10; extra == "verify"
Provides-Extra: signing
Requires-Dist: cryptography>=42; extra == "signing"
Provides-Extra: sim
Requires-Dist: qiskit-aer>=0.15; extra == "sim"
Provides-Extra: qir
Requires-Dist: qdk<2,>=1.30; extra == "qir"
Requires-Dist: pyqir<1,>=0.10; extra == "qir"
Requires-Dist: qirrunner<1,>=0.9; extra == "qir"
Dynamic: license-file

# ZentroQ SDK

Certify a quantum software release straight from your **Qrisp / Qiskit / Cirq / Braket / PennyLane** pipeline.
Evidence is collected locally (your source never leaves the machine) and sent to
the ZentroQ service, which returns a signed, independently-verifiable CRA
certificate — also mirrored to `./.zentroq/<release>/`.

ZentroQ is a [SecQDevOps](https://certify.zortenet.eu) MOD-08 service.

## Install

```bash
pip install "zentroq[quantum]"     # Qiskit + OpenQASM3 evidence collection
# pip install "zentroq[quantum,qrisp]"   # also collect from Qrisp circuits
# pip install "zentroq[quantum,cirq]"    # Cirq   — likewise [braket], [pennylane], [cudaq] (Linux only)
# pip install "zentroq[quantum,ibm]"     # real IBM Runtime execution evidence
# pip install "zentroq[quantum,qir]"     # also emit QIR (QDK) and check it against the program (QNT-07)
# pip install "zentroq[signing]"         # sign your evidence (zentroq keygen / --sign) and verify certificates offline
# Each frontend extra pins the version range the conformance suite holds for
# (harness_manifest.json `requires`); `zentroq actions --framework <name>` shows
# the recorded run, or that conformance is still pending.
```

The core install is a lightweight, stdlib-only client; the `quantum` extra adds
the toolchain needed to build the evidence (QBOM).

## Use

Set your API key (generate it in the ZentroQ dashboard):

```bash
export ZENTROQ_API_KEY=zq_live_...
export ZENTROQ_API_URL=https://certify.zortenet.eu   # default
```

**Post-run call**

```python
import zentroq
result = zentroq.certify(my_circuit, release="portfolio-opt@1.2.3")
print(result["overall_status"], result["certificate"]["certificate_id"])
```

**Decorator** — certifies the circuit a function returns:

```python
@zentroq.certified(release="vqe@2.1")
def build(): ...   # returns a qiskit/qrisp circuit
```

**Qiskit primitive wrapper** — certify transparently on `.run()`:

```python
sampler = zentroq.wrap(SamplerV2(mode=backend), release="vqe@2.1")
job = sampler.run([circuit])   # certifies, then runs as normal
```

**Sign your evidence** — the certificate's authorship claim (CRA-SIGN-01)
rests on *your* signature, not the service's. One key per organisation:

```bash
pip install "zentroq[signing]"
zentroq keygen                                   # ~/.zentroq/signing.key (0600) + signing.pub — back it up
zentroq certify --qpy circuit.qpy --release my-app@1.0 --sign
```

In Python: `zentroq.certify(circuit, release=..., sign=True)`. The SDK signs
the collected evidence (Ed25519, in-toto/DSSE) before upload; the service
verifies it, countersigns what it received, and the certificate names both
key ids. Without `--sign` the release is **NON_COMPLIANT**: CRA-SIGN-01 rests
on the producer's signature, the service's countersignature is a receipt and
never substitutes, and the certificate says in words that the producer did
not sign. `--key FILE` or `ZENTROQ_SIGNING_KEY` point at a key elsewhere; in
CI, store the key as a secret and pass it to the `zentroq-certify` action's
`signing-key` input.

**Verify a certificate without trusting us** — for the auditor, the customer,
or your future self. Needs only the wheel, never the service code:

```bash
pip install "zentroq[signing]"
zentroq keys --pin                        # fetch the service's signing keys once; pin them
zentroq verify .zentroq/my-app@1.0        # the mirror, a collect bundle, or a zip of either
```

It re-hashes every artifact against the QBOM, verifies the producer's
attestation and the service's receipt, recomputes the CSNAP's and the
certificate's reproducibility hashes and bindings, and checks the certificate
signature against a key that is *anchored* (pinned from `/v1/keys`, or given
with `--keys` / `--service-key`). What it does not do, it says: the 23
controls are not re-run (that needs the gate, `verify_bundle.py` in the
repository). Verdicts: `VERIFIED` (exit 0), `FAILED`, or `UNANCHORED` when
every check passed but nothing was pinned.

**CLI / CI**

```bash
zentroq certify --qpy circuit.qpy --release my-app@1.0 --mode gate --sign
zentroq certify --qasm3 program.qasm3 --release my-app@1.0
zentroq certify --demo --release smoke-test     # needs the [qrisp] extra

# any supported framework, straight from your code (module:attr or file.py:attr;
# a function is called, an object such as a PennyLane QNode is passed as is)
zentroq certify --entry my_pkg.circuits:build --release my-app@1.0 --expect 10=1.0
```

`--mode gate` exits non-zero on a non-compliant release (use it to fail CI);
`--mode report` (default) never fails your pipeline. `--expect` outcomes are
read in your framework's own bit order (`--expected-order qiskit` to override).
For Qrisp that depends on what you hand over: a `QuantumCircuit` reads like
`run()` (qubit 0 rightmost), a `QuantumSession` like `get_measurement()` and a
Jasp program like `measure()` (qubit 0 leftmost) — declare what Qrisp shows you.

**Adding evidence from other modules** — collect, add, then certify the bundle:

```bash
zentroq collect --entry my_pkg.circuits:build --release my-app@1.0 --out bundle/
zentroq attest tests         --bundle bundle/ --suite quantum-security-suite --outcome passed --passed 42
zentroq attest vulns         --bundle bundle/ --policy-url https://example.org/security --contact mailto:security@example.org
zentroq attest constant-time --bundle bundle/ --tool dudect --target kyber_decaps --measurements timings.csv
zentroq attest crypto        --bundle bundle/ --cbom cbom.cdx.json
zentroq sign --bundle bundle/                    # last, so the signature covers it all
zentroq certify --bundle bundle/ --release my-app@1.0
```

The four `attest` commands are the partner-module evidence the gate otherwise
reports as N-A: a MOD-05 security test report (`MOD05-TEST-01`), a VEX/VDR and
a coordinated-disclosure policy (`CRA-VULN-01`, `CRA-VDP-01`), a constant-time
proof from dudect / ctgrind / Binsec-Rel (`CRA-ESR-06`), and a CBOM
PQC-readiness assessment (`CRA-CRYPTO-01`). Each writes a hash-bound document
into the bundle; the same bytes the repository scripts write.

In Python: `zentroq.collect(...)`, then `zentroq.attest.tests(bundle, ...)`,
`.vulnerability_handling(...)`, `.constant_time(...)`, `.crypto(...)`, then
`zentroq.certify(bundle="bundle", release=..., sign=True)`.

**What can the harness do for me?**

```bash
zentroq actions --framework cirq          # every action, its status for Cirq, how to turn it on
zentroq actions --requirement CRA-II-3    # which actions produce evidence for this requirement
```

Answered offline from the index shipped in the package — the same answer the
service gives at `GET /v1/harness`.

## Behaviour

- **Non-intrusive & fail-soft.** If the service is unreachable or credits are
  exhausted, a warning is logged and your quantum run continues. Certifying is
  additive (unless you opt into `gate` mode).
- **Privacy by design.** Only the QBOM/evidence (hashes, metrics, backend
  binding) is uploaded — not your program source.
- **Local mirror.** Every result is written to `./.zentroq/<release>/`
  (the QBOM as the gate ran on it, CSNAP, certificate, attestation, the
  service's receipt and public keys, verification) so you keep your own
  audit bundle and can re-verify it offline with `zentroq verify`.

| Env var | Purpose |
|---|---|
| `ZENTROQ_API_KEY` | your API key (required for actions) |
| `ZENTROQ_API_URL` | service base URL (default `https://certify.zortenet.eu`) |
| `ZENTROQ_SIGNING_KEY` | producer signing key for `--sign` (default `~/.zentroq/signing.key`) |
