Skip to main content

Guia de Integração QuantumLock em Produtos SoftQuantus

Visão Geral

Este guia explica como integrar o sistema de licenciamento QuantumLock em qualquer produto SoftQuantus (QCOS, SynapseX, etc.).


Fluxo Completo

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────────────────┐
│ ADMIN │───▶│ QUANTUMLOCK API │───▶│ BANCO DE DADOS PORTAL │
│ Cria Licença │ │ Gera Assinatura │ │ Armazena license_key │
└─────────────────┘ └──────────────────┘ └─────────────────────────────┘

┌─────────────────────────────┘

┌─────────────────┐ ┌──────────────────┐ ┌─────────────────────────────┐
│ CLIENTE │◀───│ PORTAL │ │ ARQUIVO .lic │
│ Recebe Licença │ │ Download/Copia │───▶│ ou license_key │
└─────────────────┘ └──────────────────┘ └─────────────────────────────┘

┌─────────────────────────────┘

┌─────────────────┐ ┌──────────────────┐ ┌─────────────────────────────┐
│ PRODUTO │ │ quantumlock-sdk │ │ VALIDAÇÃO │
│ SDK/CLI/API │───▶│ LicenseValidator│───▶│ • Offline (assinatura) │
│ │ │ │ │ • Online (API - opcional) │
└─────────────────┘ └──────────────────┘ └─────────────────────────────┘

1. Instalação do SDK

pip install quantumlock-sdk

Ou via requirements.txt:

quantumlock-sdk>=2.0.0

2. Integração em SDK Python

Arquivo: your_product/licensing.py

"""
Módulo de Licenciamento do Produto
"""
import os
from pathlib import Path
from typing import Optional
from quantumlock import LicenseValidator, LicenseError, FeatureNotLicensed


class ProductLicense:
"""Gerenciador de licença do produto."""

# Caminhos padrão para procurar licença
DEFAULT_PATHS = [
Path.home() / ".your_product" / "license.lic",
Path("/etc/your_product/license.lic"),
Path("./license.lic"),
]

def __init__(
self,
license_file: Optional[str] = None,
license_key: Optional[str] = None,
online_validation: bool = True,
):
"""
Inicializa o gerenciador de licença.

Args:
license_file: Caminho para arquivo .lic
license_key: License key (alternativa ao arquivo)
online_validation: Validar online quando possível
"""
self.validator = LicenseValidator(
online_validation=online_validation,
api_url="https://quantumlock.softquantus.com",
)
self._license_file = license_file
self._license_key = license_key
self._validated = False

def find_license(self) -> Optional[Path]:
"""Procura arquivo de licença nos caminhos padrão."""
# 1. Verificar variável de ambiente
env_path = os.getenv("YOUR_PRODUCT_LICENSE")
if env_path and Path(env_path).exists():
return Path(env_path)

# 2. Verificar parâmetro
if self._license_file and Path(self._license_file).exists():
return Path(self._license_file)

# 3. Procurar nos caminhos padrão
for path in self.DEFAULT_PATHS:
if path.exists():
return path

return None

def validate(self) -> bool:
"""
Valida a licença.

Returns:
True se válida

Raises:
LicenseError: Se licença inválida ou não encontrada
"""
license_path = self.find_license()

if not license_path:
raise LicenseError(
"Licença não encontrada. Configure via:\n"
" 1. Variável de ambiente: YOUR_PRODUCT_LICENSE=/path/to/license.lic\n"
" 2. Arquivo em: ~/.your_product/license.lic\n"
" 3. Parâmetro: ProductLicense(license_file='/path/to/license.lic')\n"
"\nObtenha sua licença em: https://portal.softquantus.com"
)

self._validated = self.validator.validate(str(license_path))
return self._validated

def require_valid(self):
"""Exige licença válida ou levanta exceção."""
if not self._validated:
if not self.validate():
raise LicenseError("Licença inválida ou expirada")

def has_feature(self, feature: str) -> bool:
"""Verifica se feature está licenciada."""
self.require_valid()
return self.validator.has_feature(feature)

def require_feature(self, feature: str):
"""Decorator para exigir feature específica."""
return self.validator.require_feature(feature)

@property
def info(self) -> dict:
"""Retorna informações da licença."""
if not self._validated:
try:
self.validate()
except LicenseError:
return {"valid": False, "error": "No license"}
return self.validator.get_license_info()


# Instância global (opcional)
_license: Optional[ProductLicense] = None


def get_license() -> ProductLicense:
"""Retorna instância global da licença."""
global _license
if _license is None:
_license = ProductLicense()
return _license


def require_license(func):
"""Decorator para exigir licença válida."""
from functools import wraps

@wraps(func)
def wrapper(*args, **kwargs):
get_license().require_valid()
return func(*args, **kwargs)
return wrapper


def require_feature(feature: str):
"""Decorator para exigir feature específica."""
def decorator(func):
from functools import wraps

@wraps(func)
def wrapper(*args, **kwargs):
lic = get_license()
if not lic.has_feature(feature):
raise FeatureNotLicensed(
f"Feature '{feature}' não está licenciada. "
f"Upgrade em: https://portal.softquantus.com"
)
return func(*args, **kwargs)
return wrapper
return decorator

Uso no código do produto:

# your_product/client.py
from .licensing import require_license, require_feature, get_license

class YourProductClient:
"""Cliente principal do produto."""

def __init__(self, license_file: str = None):
# Inicializa e valida licença
from .licensing import ProductLicense
self._license = ProductLicense(license_file=license_file)
self._license.validate() # Levanta exceção se inválida

@require_license
def basic_operation(self):
"""Operação básica - requer licença válida."""
return "result"

@require_feature("premium")
def premium_operation(self):
"""Operação premium - requer feature 'premium'."""
return "premium result"

@require_feature("autopilot")
def autopilot_optimize(self, circuit):
"""Otimização com Autopilot - requer feature 'autopilot'."""
return self._run_autopilot(circuit)

@property
def license_info(self) -> dict:
"""Informações da licença atual."""
return self._license.info

3. Integração em CLI

Arquivo: your_product/cli/main.py

"""
CLI do Produto com Licenciamento
"""
import typer
import sys
from pathlib import Path
from typing import Optional

app = typer.Typer(help="Your Product CLI")

# Variável global para licença
LICENSE_KEY_ENV = "YOUR_PRODUCT_LICENSE_KEY"
LICENSE_FILE_ENV = "YOUR_PRODUCT_LICENSE"


def get_license_validator():
"""Obtém validador de licença."""
from quantumlock import LicenseValidator
return LicenseValidator(
online_validation=True,
api_url="https://quantumlock.softquantus.com"
)


def validate_license_or_exit(license_file: Optional[str] = None):
"""Valida licença ou encerra com erro."""
import os

# Procurar licença
paths_to_check = []

if license_file:
paths_to_check.append(Path(license_file))

if os.getenv(LICENSE_FILE_ENV):
paths_to_check.append(Path(os.getenv(LICENSE_FILE_ENV)))

paths_to_check.extend([
Path.home() / ".your_product" / "license.lic",
Path("/etc/your_product/license.lic"),
Path("./license.lic"),
])

validator = get_license_validator()

for path in paths_to_check:
if path.exists():
try:
if validator.validate(str(path)):
return validator
except Exception:
continue

typer.echo("❌ Licença não encontrada ou inválida!", err=True)
typer.echo("\nPara ativar:", err=True)
typer.echo(" 1. your-product activate --license-key 'SUA-CHAVE'", err=True)
typer.echo(" 2. Ou configure: export YOUR_PRODUCT_LICENSE=/path/to/license.lic", err=True)
typer.echo("\nObtenha sua licença em: https://portal.softquantus.com", err=True)
raise typer.Exit(1)


@app.command()
def activate(
license_key: str = typer.Option(None, "--license-key", "-k", help="License key"),
license_file: str = typer.Option(None, "--license-file", "-f", help="License file path"),
):
"""Ativa o produto com uma licença."""
import os
import json
import base64
import requests

if not license_key and not license_file:
typer.echo("❌ Forneça --license-key ou --license-file", err=True)
raise typer.Exit(1)

if license_file:
# Copiar arquivo para diretório padrão
license_path = Path(license_file)
if not license_path.exists():
typer.echo(f"❌ Arquivo não encontrado: {license_file}", err=True)
raise typer.Exit(1)

dest_dir = Path.home() / ".your_product"
dest_dir.mkdir(parents=True, exist_ok=True)
dest_file = dest_dir / "license.lic"

import shutil
shutil.copy(license_path, dest_file)
typer.echo(f"✅ Licença instalada em: {dest_file}")

elif license_key:
# Validar license_key via API e salvar
typer.echo(f"🔍 Validando licença...")

try:
response = requests.post(
"https://quantumlock.softquantus.com/api/v1/licenses/validate",
json={
"license_key": license_key,
"end_customer_id": os.getenv("USER", "cli-user"),
},
timeout=10,
)

if response.status_code == 200 and response.json().get("valid"):
# Salvar licença
dest_dir = Path.home() / ".your_product"
dest_dir.mkdir(parents=True, exist_ok=True)

# Criar arquivo .lic
license_data = {
"license_key": license_key,
"quantum_signature": "validated-via-api",
"valid_until": response.json().get("expires_at", "2099-12-31"),
"features": response.json().get("features", []),
}

license_content = base64.b64encode(
json.dumps(license_data).encode()
).decode()

dest_file = dest_dir / "license.lic"
dest_file.write_text(license_content)

typer.echo(f"✅ Licença ativada com sucesso!")
typer.echo(f" Arquivo: {dest_file}")
typer.echo(f" Expira: {license_data['valid_until']}")
typer.echo(f" Features: {', '.join(license_data['features'])}")
else:
typer.echo("❌ Licença inválida ou expirada", err=True)
raise typer.Exit(1)

except requests.RequestException as e:
typer.echo(f"❌ Erro ao validar: {e}", err=True)
raise typer.Exit(1)


@app.command()
def status():
"""Mostra status da licença atual."""
validator = validate_license_or_exit()
info = validator.get_license_info()

typer.echo("📋 Status da Licença:")
typer.echo(f" ✅ Válida: {info['valid']}")
typer.echo(f" 🔑 Key: {info['license_key'][:20]}...")
typer.echo(f" 📅 Expira: {info['valid_until']}")
typer.echo(f" 🔮 Quantum Verified: {info['quantum_verified']}")
typer.echo(f" 📦 Features: {', '.join(info['features'])}")


@app.command()
def run(
script: str = typer.Argument(..., help="Script to run"),
license_file: str = typer.Option(None, "--license", "-l", help="License file"),
):
"""Executa um script (requer licença válida)."""
validator = validate_license_or_exit(license_file)

typer.echo(f"🚀 Executando: {script}")
# ... sua lógica de execução


@app.command()
def optimize(
script: str = typer.Argument(..., help="Script to optimize"),
):
"""Otimiza um script (requer feature 'autopilot')."""
validator = validate_license_or_exit()

if not validator.has_feature("autopilot"):
typer.echo("❌ Feature 'autopilot' não está licenciada!", err=True)
typer.echo(" Upgrade em: https://portal.softquantus.com", err=True)
raise typer.Exit(1)

typer.echo(f"🔮 Otimizando com Autopilot: {script}")
# ... sua lógica de otimização


if __name__ == "__main__":
app()

4. Integração em API (FastAPI)

Arquivo: your_product/api/deps.py

"""
Dependências da API incluindo validação de licença.
"""
from fastapi import Header, HTTPException, Depends
from typing import Optional
import os

from quantumlock import LicenseValidator, LicenseError


# Cache de validadores
_validator_cache = {}


async def get_license_validator(
x_license_key: Optional[str] = Header(None, alias="X-License-Key"),
x_license_file: Optional[str] = Header(None, alias="X-License-File"),
) -> LicenseValidator:
"""
Dependency para validar licença em cada request.

Headers aceitos:
X-License-Key: QCOS-1234-...
X-License-File: /path/to/license.lic
"""
validator = LicenseValidator(
online_validation=True,
api_url="https://quantumlock.softquantus.com",
)

# Tentar validar por arquivo
if x_license_file and os.path.exists(x_license_file):
try:
if validator.validate(x_license_file):
return validator
except LicenseError as e:
raise HTTPException(status_code=403, detail=str(e))

# Tentar validar por key via API
if x_license_key:
import httpx

try:
async with httpx.AsyncClient() as client:
response = await client.post(
"https://quantumlock.softquantus.com/api/v1/licenses/validate",
json={
"license_key": x_license_key,
"end_customer_id": "api-client",
},
timeout=5.0,
)

if response.status_code == 200 and response.json().get("valid"):
# Criar validator fake com dados da resposta
validator._license_data = response.json()
validator._is_valid = True
return validator

except Exception:
pass

raise HTTPException(
status_code=401,
detail="Licença não fornecida ou inválida. "
"Inclua header X-License-Key ou X-License-File."
)


def require_feature(feature: str):
"""Dependency factory para exigir feature específica."""

async def check_feature(
validator: LicenseValidator = Depends(get_license_validator)
) -> LicenseValidator:
if not validator.has_feature(feature):
raise HTTPException(
status_code=403,
detail=f"Feature '{feature}' não licenciada. "
f"Upgrade em: https://portal.softquantus.com"
)
return validator

return check_feature

Arquivo: your_product/api/routes.py

"""
Rotas da API com proteção de licença.
"""
from fastapi import APIRouter, Depends
from .deps import get_license_validator, require_feature
from quantumlock import LicenseValidator

router = APIRouter()


@router.get("/status")
async def get_status(
validator: LicenseValidator = Depends(get_license_validator)
):
"""Status da licença (requer licença válida)."""
return {
"status": "active",
"license": validator.get_license_info()
}


@router.post("/run")
async def run_job(
job: dict,
validator: LicenseValidator = Depends(get_license_validator)
):
"""Executa job (requer licença válida)."""
# Verificar limite de qubits se definido
info = validator.get_license_info()
max_qubits = info.get("features", [])

# ... lógica de execução
return {"result": "success"}


@router.post("/optimize")
async def optimize_circuit(
circuit: dict,
validator: LicenseValidator = Depends(require_feature("autopilot"))
):
"""Otimiza circuito (requer feature 'autopilot')."""
# ... lógica de otimização
return {"optimized": True}


@router.post("/distributed")
async def distributed_run(
job: dict,
validator: LicenseValidator = Depends(require_feature("distributed"))
):
"""Execução distribuída (requer feature 'distributed')."""
# ... lógica distribuída
return {"nodes": 4, "result": "success"}

5. Variáveis de Ambiente Recomendadas

# Arquivo de licença
YOUR_PRODUCT_LICENSE=/path/to/license.lic

# Ou license key diretamente
YOUR_PRODUCT_LICENSE_KEY=QCOS-1234-...

# Para validação online (opcional)
QUANTUMLOCK_API_URL=https://quantumlock.softquantus.com

6. Features Padrão por Tipo de Licença

TipoFeatures Incluídas
startercore, optimization
professionalcore, optimization, cloud
enterprisecore, optimization, cloud, distributed, autopilot

7. Publicação do Produto

PyPI (SDK)

# Adicionar dependência no pyproject.toml
[project]
dependencies = [
"quantumlock-sdk>=2.0.0",
# ... outras deps
]

# Build e publish
python -m build
twine upload dist/*

Docker (API)

FROM python:3.11-slim

# Instalar dependências incluindo quantumlock-sdk
COPY requirements.txt .
RUN pip install -r requirements.txt

# Copiar código
COPY . /app
WORKDIR /app

# Variável para licença (montada em runtime)
ENV YOUR_PRODUCT_LICENSE=/etc/license/license.lic

CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"]

GitHub Releases (CLI)

# Build binário com Nuitka
nuitka --onefile --output-dir=dist your_product/cli/main.py

# Upload para GitHub Releases
gh release create v1.0.0 dist/your_product --title "v1.0.0"

8. Exemplo de Uso pelo Cliente

# Instalar
pip install your-product

# Ativar
your-product activate --license-key "QCOS-1234-..."

# Usar SDK
from your_product import Client

client = Client() # Usa licença de ~/.your_product/license.lic
result = client.run(my_job)

# Ou com licença explícita
client = Client(license_file="/custom/path/license.lic")

Suporte