Skip to main content

SDK Python completo para a API HighBond - Projects, Risks, Controls e Issues com paginação automática e multithreading

Project description

HighBond SDK

Version Python Version License: MIT

Versão 0.0.4 - SDK Python em desenvolvimento para a API HighBond com suporte a Projects, Objectives, Risks, Controls, Project Types e Issues.

✨ Features

  • 🚀 Paginação automática - Itera sobre milhares de registros sem se preocupar com paginação
  • Multithreading - Busca múltiplos recursos em paralelo para máxima performance
  • 🔄 Retry automático - Tratamento inteligente de rate limits e erros de conexão
  • 📊 DataFrames - Retorne dados em formato pandas DataFrame para análise rápida
  • 📝 Tipagem completa - Type hints para melhor autocompletar e validação
  • 🎯 API intuitiva - Interface fluente e fácil de usar
  • 🛡️ Tratamento de erros - Exceções específicas para cada tipo de erro

📦 Instalação

pip install highbond-sdk

🚀 Quick Start

from highbond_sdk import HighBondClient

# Inicializar cliente
client = HighBondClient(
    token="seu_token_aqui",
    org_id=12345,        # int - ID da organização
    region="us"          # "us", "eu", "au", "ca" ou "sa"
)

# ===== PROJETOS =====
# Listar projetos com paginação manual
response = client.projects.list(page=1, page_size=25)
for projeto in response['data']:
    print(f"Projeto: {projeto['attributes']['name']}")

# Listar todos os projetos (paginação automática)
for projeto in client.projects.list_all():
    print(f"- {projeto['id']}: {projeto['attributes']['name']}")

# Retornar como DataFrame (pandas)
df_projetos = client.projects.list_all(return_pandas=True)
print(df_projetos)

# Buscar projeto específico
projeto = client.projects.get(546355)
print(f"Projeto: {projeto['data']['attributes']['name']}")

# ===== TIPOS DE PROJETO =====
# Listar tipos de projeto como DataFrame
df_tipos = client.project_types.list_all(return_pandas=True)
print(df_tipos)

# ===== RISCOS =====
# Listar todos os riscos da organização (com project_id adicionado automaticamente)
df_todos_riscos = client.risks.list_all(return_pandas=True)
print(df_todos_riscos)

# Listar riscos de um projeto específico
df_riscos_projeto = client.risks.list_by_project(project_id=546355, return_pandas=True)
print(df_riscos_projeto)

# Listar riscos de um objetivo específico
df_riscos_objetivo = client.risks.list_by_objective(objective_id=1990741, return_pandas=True)
print(df_riscos_objetivo)

# ===== CONTROLES =====
# Listar todos os controles
df_controles = client.controls.list_all(return_pandas=True)
print(df_controles)

# Listar controles de um projeto
df_controles_projeto = client.controls.list_by_project(project_id=510117, return_pandas=True)
print(df_controles_projeto)

# Listar controles de um objetivo
df_controles_objetivo = client.controls.list_by_objective(objective_id=1924816, return_pandas=True)
print(df_controles_objetivo)

📖 Documentação Completa

Configuração Avançada

from highbond_sdk import HighBondClient

client = HighBondClient(
    token="seu_token",
    org_id=12345,
    region="us",
    timeout=60,              # Timeout em segundos
    max_retries=5,           # Tentativas em caso de erro
    retry_delay=1.0,         # Delay inicial entre tentativas
    page_size=50,            # Itens por página (max 100)
    max_pages=None,          # Sem limite de páginas
    max_workers=5,           # Workers paralelos
    threading_enabled=True   # Habilitar multithreading
)

# Usando context manager
with HighBondClient(token="...", org_id=12345) as client:
    projetos = client.projects.list_all(return_pandas=True)

📊 Retornando Dados como DataFrame

Todos os métodos de listagem agora suportam o parâmetro return_pandas:

import pandas as pd

# JSON (padrão)
riscos_lista = client.risks.list_all()

# DataFrame (pandas)
riscos_df = client.risks.list_all(return_pandas=True)
print(riscos_df.head())

# Funciona em todos os módulos
df_projetos = client.projects.list_all(return_pandas=True)
df_controles = client.controls.list_all(return_pandas=True)
df_objetivos = client.objectives.list_all_by_project(project_id=123, return_pandas=True)
df_tipos = client.project_types.list_all(return_pandas=True)

Projects

# Listar projetos (paginação manual)
response = client.projects.list(page=1, page_size=50)

# Listar todos (retorna lista)
projetos = client.projects.list_all()
for projeto in projetos:
    print(projeto["attributes"]["name"])

# Ou como DataFrame para análise
df = client.projects.list_all(return_pandas=True)
print(df.head())

# Buscar projeto específico
projeto = client.projects.get(546355)
print(f"Projeto: {projeto['data']['attributes']['name']}")

# Buscar múltiplos em paralelo
projetos = client.projects.get_many([546355, 541532, 510092])

# Criar projeto (campos obrigatórios: name, project_type_id, start_date, target_date)
novo = client.projects.create(
    name="Auditoria 2024",
    project_type_id=42,           # ID do tipo de projeto
    start_date="2024-01-01",      # Data de início (YYYY-MM-DD)
    target_date="2024-12-31",     # Data alvo (YYYY-MM-DD)
    description="Descrição do projeto",
    background="Contexto do projeto"
)

# Atualizar projeto
client.projects.update(546355, name="Novo Nome", status="active")

# Deletar projeto
client.projects.delete(546355)

Project Types

# Listar tipos de projeto
tipos = client.project_types.list_all()

# Como DataFrame (útil para análise)
df_tipos = client.project_types.list_all(return_pandas=True)
print(df_tipos[['id', 'attributes.name', 'attributes.description']])

# Buscar tipo específico
tipo = client.project_types.get(42)

# Buscar múltiplos tipos em paralelo
tipos = client.project_types.get_many([1, 2, 3])

Objectives

# Listar objetivos de um projeto
objetivos = client.objectives.list_all_by_project(project_id=546355)

# Como DataFrame
df_obj = client.objectives.list_all_by_project(
    project_id=546355,
    return_pandas=True
)
print(df_obj)

# Buscar objetivo
objetivo = client.objectives.get(project_id=546355, objective_id=1990741)

# Criar objetivo
novo = client.objectives.create(
    project_id=546355,
    title="Revisão de Controles"
)

# Atualizar objetivo
client.objectives.update(
    project_id=546355,
    objective_id=1990741,
    title="Novo Título"
)

# Deletar objetivo
client.objectives.delete(project_id=546355, objective_id=1990741)

Risks

IMPORTANTE: Riscos são criados dentro de Objectives, não diretamente em Projects. O campo project_id é adicionado automaticamente em riscos para melhor rastreabilidade.

# Listar TODOS os riscos da organização (busca projetos → objetivos → riscos)
# Retorna também o project_id de cada risco
riscos = client.risks.list_all()
riscos_df = client.risks.list_all(return_pandas=True)

# Listar riscos de um projeto específico
riscos_projeto = client.risks.list_by_project(project_id=546355)
riscos_projeto_df = client.risks.list_by_project(
    project_id=546355,
    return_pandas=True  # Retorna como DataFrame
)

# Listar riscos de um objetivo específico
riscos_obj = client.risks.list_by_objective(objective_id=1990741)
riscos_obj_df = client.risks.list_by_objective(
    objective_id=1990741,
    return_pandas=True
)

# Buscar risco
risco = client.risks.get(risk_id=8454148)

# Buscar múltiplos em paralelo
riscos = client.risks.get_many([8454148, 8454149, 8454150])

# Criar risco (dentro de um objetivo)
novo = client.risks.create(
    objective_id=1990741,
    description="Descrição detalhada do risco",
    title="Título do Risco",
    impact="High",
    likelihood="Medium",
    owner="responsavel@empresa.com"
)

# Atualizar risco
client.risks.update(risk_id=8454148, impact="Low", title="Novo Título")

# Vincular controle a um risco
client.risks.link_control(risk_id=8454148, control_id=789)

# Desvincular controle
client.risks.unlink_control(risk_id=8454148, control_id=789)

# Obter controles vinculados
controles = client.risks.get_controls(risk_id=8454148)

# Deletar risco
client.risks.delete(risk_id=8454148)

Controls

IMPORTANTE: Controles são criados dentro de Objectives, não diretamente em Projects. Para projetos de workflow "Internal Control", os campos frequency, control_type e prevent_detect são obrigatórios.

# Listar TODOS os controles da organização
controles = client.controls.list_all()
controles_df = client.controls.list_all(return_pandas=True)

# Listar controles de um projeto (busca objetivos do projeto → seus controles)
controles_projeto = client.controls.list_by_project(project_id=510117)
controles_projeto_df = client.controls.list_by_project(
    project_id=510117,
    return_pandas=True
)

# Listar controles de um objetivo
controles_obj = client.controls.list_by_objective(objective_id=1924816)
controles_obj_df = client.controls.list_by_objective(
    objective_id=1924816,
    return_pandas=True
)

# Buscar controle
controle = client.controls.get(control_id=789)

# Buscar múltiplos em paralelo
controles = client.controls.get_many([789, 790, 791])

# Criar controle - Internal Control workflow (obrigatórios: frequency, control_type, prevent_detect)
novo_ic = client.controls.create(
    objective_id=1924816,
    description="Descrição detalhada do controle",
    title="Controle de Aprovação",
    frequency="Daily",
    control_type="Manual Control",
    prevent_detect="Prevent",
    owner="responsavel@empresa.com"
)

# Criar controle - Workplan workflow (procedimentos)
novo_wp = client.controls.create(
    objective_id=1924816,
    description="Descrição do procedimento",
    title="Procedimento de Auditoria"
)

# Atualizar controle
client.controls.update(control_id=789, status="Key Control")

# Vincular risco a um controle
client.controls.link_risk(control_id=789, risk_id=8454148)

# Desvincular risco
client.controls.unlink_risk(control_id=789, risk_id=8454148)

# Obter riscos vinculados
riscos = client.controls.get_risks(control_id=789)

# Obter testes do controle
testes = client.controls.get_tests(control_id=789)

# Deletar controle
client.controls.delete(control_id=789)

Issues

IMPORTANTE: Issues são criadas em Projects (não em Objectives). Campos obrigatórios: description, deficiency_type, e owner (ou owner_user_uid).

# Listar todas as issues da organização
issues = client.issues.list_all()

# Listar issues de um projeto
issues_projeto = client.issues.list_all_by_project(project_id=546355)

# Buscar issue
issue = client.issues.get(issue_id=999)

# Criar issue
nova = client.issues.create(
    project_id=546355,
    description="<p>Descrição detalhada da deficiência</p>",
    deficiency_type="Deficiency",
    owner="responsavel@empresa.com",
    title="Deficiência de Controle",
    severity="High",
    recommendation="<p>Recomendação de ação</p>",
    remediation_date="2024-12-31"
)

# OU usando UID do usuário (sobrescreve owner)
nova = client.issues.create(
    project_id=546355,
    description="Descrição da issue",
    deficiency_type="Significant Deficiency",
    owner_user_uid="3NQ6XzAUxqJMnAQ7n4KF",
    severity="Critical"
)

# Atualizar issue
client.issues.update(
    issue_id=999,
    remediation_status="Closed",
    actual_remediation_date="2024-06-15"
)

# Fechar issue
client.issues.close(issue_id=999)

# Reabrir issue
client.issues.reopen(issue_id=999)

Tratamento de Erros

from highbond_sdk import (
    HighBondAPIError,
    HighBondAuthError,
    HighBondForbiddenError,
    HighBondNotFoundError,
    HighBondValidationError,
    HighBondRateLimitError,
    HighBondConnectionError
)

try:
    projeto = client.projects.get(999999)
except HighBondNotFoundError as e:
    print(f"Projeto não encontrado: {e}")
except HighBondAuthError as e:
    print(f"Token inválido ou expirado: {e}")
except HighBondForbiddenError as e:
    print(f"Sem permissão para acessar: {e}")
except HighBondValidationError as e:
    print(f"Erro de validação: {e}")
except HighBondRateLimitError as e:
    print(f"Limite de requisições excedido: {e}")
except HighBondConnectionError as e:
    print(f"Erro de conexão: {e}")
except HighBondAPIError as e:
    print(f"Erro da API: {e} (status: {e.status_code})")

💡 Exemplos Práticos

Exemplo 1: Análise de Riscos por Projeto

from highbond_sdk import HighBondClient

client = HighBondClient(
    token="seu_token",
    org_id=12345,
    region="us"
)

# Obter todos os riscos como DataFrame
df_riscos = client.risks.list_all(return_pandas=True)

# Filtrar por project_id
project_id = 546355
riscos_projeto = df_riscos[df_riscos['project_id'] == project_id]

# Agrupar por impacto
print("Riscos por Impacto:")
print(riscos_projeto.groupby('attributes.impact').size())

# Exportar para CSV
riscos_projeto.to_csv('riscos_projeto.csv', index=False)

Exemplo 2: Controles não Vinculados a Riscos

# Obter todos os controles
df_controles = client.controls.list_all(return_pandas=True)

# Identificar controles que podem precisar de riscos
print(f"Total de controles: {len(df_controles)}")

# Verificar status de implementação
print("\nControles por Status:")
print(df_controles['attributes.status'].value_counts())

Exemplo 3: Criar Múltiplos Riscos em Paralelo

# Listar objetivos
objetivos = client.objectives.list_all_by_project(project_id=546355)

# Criar riscos para cada objetivo
for objetivo in objetivos:
    risco = client.risks.create(
        objective_id=objetivo['id'],
        description=f"Risco padrão para {objetivo['attributes']['title']}",
        title=f"Risco - {objetivo['attributes']['title']}",
        impact="Medium",
        likelihood="Medium"
    )
    print(f"Risco criado para objetivo {objetivo['id']}")

Exemplo 4: Dashboard com Estatísticas

import pandas as pd

client = HighBondClient(token="seu_token", org_id=12345, region="us")

# Coletar dados
df_projetos = client.projects.list_all(return_pandas=True)
df_riscos = client.risks.list_all(return_pandas=True)
df_controles = client.controls.list_all(return_pandas=True)

print("=" * 50)
print("DASHBOARD HIGHBOND")
print("=" * 50)

print(f"\nTotal de Projetos: {len(df_projetos)}")
print(f"Total de Riscos: {len(df_riscos)}")
print(f"Total de Controles: {len(df_controles)}")

print("\nRiscos por Impacto:")
print(df_riscos['attributes.impact'].value_counts())

print("\nControles por Projeto:")
print(df_controles['project_id'].value_counts())

print("\nProjetos Ativos:")
ativos = df_projetos[df_projetos['attributes.status'] == 'active']
print(f"{len(ativos)} projetos")

🔧 Regiões Suportadas

Região Valor URL Base
Estados Unidos us https://apis-us.highbond.com/v1
Europa eu https://apis-eu.highbond.com/v1
Austrália au https://apis-au.highbond.com/v1
Canadá ca https://apis-ca.highbond.com/v1
América do Sul sa https://apis-sa.diligentoneplatform.com/v1

📊 Valores de Campos Configuráveis

A maioria dos campos da API HighBond usa strings configuráveis no project type. Os valores abaixo são exemplos comuns - verifique as opções disponíveis no seu project type:

Campo Exemplos de Valores
deficiency_type "Deficiency", "Significant Deficiency", "Material Weakness"
severity "High", "Medium", "Low", "Critical"
impact/likelihood "High", "Medium", "Low", "Very High", "Very Low"
frequency "Daily", "Weekly", "Monthly", "Quarterly", "Annually"
control_type "Application/System Control", "Manual Control"
prevent_detect "Prevent", "Detect", "N/A"
remediation_status "Opened", "In Progress", "Closed"
scope "Local", "Regional", "Enterprise"

📋 Requisitos

  • Python 3.8+
  • requests >= 2.28.0

🤝 Contribuindo

Contribuições são bem-vindas! Por favor, abra uma issue ou pull request.

📄 Licença

Este projeto está licenciado sob a MIT License - veja o arquivo LICENSE para detalhes.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

highbond_sdk-0.0.4.tar.gz (34.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

highbond_sdk-0.0.4-py3-none-any.whl (39.8 kB view details)

Uploaded Python 3

File details

Details for the file highbond_sdk-0.0.4.tar.gz.

File metadata

  • Download URL: highbond_sdk-0.0.4.tar.gz
  • Upload date:
  • Size: 34.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for highbond_sdk-0.0.4.tar.gz
Algorithm Hash digest
SHA256 1fe371f6fa56e173796217b1ba6cb2205dbc9704fc68c4101f732f1c18fce468
MD5 fa12e1d2b361320fb935dc5a98b58267
BLAKE2b-256 25c815717d47ce3b93866ee6b344d38b4f8fdeef78c688c586d0ddfb75461cf0

See more details on using hashes here.

File details

Details for the file highbond_sdk-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: highbond_sdk-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 39.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for highbond_sdk-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 d6a7ffc89658d3c2451bf6bf32220097b8c62cdb41759905be79d1353bfdad6b
MD5 7a9167cc1b8b51cfe38a4b307d1f7590
BLAKE2b-256 4346a1ee8eccde56d8b410c11543527ce67e71b222bdd479703deac096876308

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page