Python FastAPI wrapper for Verlihub DC hub with native C++ core (a modified fork of Verlihub, maintained at github.com/transfix/verlihub)
Project description
Verlihub Python API
A FastAPI-based REST API and web dashboard for managing Verlihub DC hubs.
Fork notice:
verlihub-pyis a modified fork of Verlihub, maintained at github.com/transfix/verlihub. It is not the original project. Licensed GPL-3.0-or-later; all upstream copyrights are preserved.
Features
- REST API - Full hub management via HTTP endpoints
- Web Dashboard - Browser-based administration UI
- WebSocket - Real-time hub events and log streaming
- CLI Tools - Command-line management utilities
- Performance Benchmarks - Load testing and performance analysis
- Remote Client - Python client library for hub administration
- NMDCpb Protocol Extension - Protobuf structured messaging with hub-relayed transfers, E2E encrypted PM, media sharing, channels, and voice/video signaling
- LLM & MCP Integration - AI chat assistant with hub tool-calling, an NMDC
Hub-Securitybot, and a Model Context Protocol server for AI editors
Quick Start
Installation
# From PyPI (recommended)
pip install verlihub-py
# With LLM / MCP integration extras (OpenAI-compatible client + MCP server)
pip install "verlihub-py[ai]"
# From source (development)
git clone https://github.com/transfix/verlihub
cd verlihub/python
pip install -e ".[dev]"
Note: the published wheels bundle the native Verlihub C++ core (built via scikit-build-core + SWIG). A source build additionally needs CMake, SWIG, a C++17 compiler, and the hub's build dependencies.
Running the API Server
# Start the API server
verlihub-api
# Or with custom settings
verlihub-api --host 0.0.0.0 --port 8000
Using the CLI
# Check hub status
verlihub-cli status
# List online users
verlihub-cli users
# Execute a hub command
verlihub-cli command "!help"
# Login and save token
verlihub-cli login admin password123
API Endpoints
Public Endpoints
| Endpoint | Description |
|---|---|
GET /health |
Health check |
GET /api/v1/hub/stats |
Hub statistics |
GET /api/v1/hub/info |
Hub information |
Authenticated Endpoints
| Endpoint | Min Class | Description |
|---|---|---|
GET /api/v1/users/online |
1 | List online users |
GET /api/v1/users/registered |
3 | List registered users |
POST /api/v1/users/{nick}/kick |
3 | Kick a user |
GET /api/v1/bans/ |
3 | List bans |
POST /api/v1/bans/ |
4 | Create a ban |
POST /api/v1/console/execute |
3 | Execute hub command |
GET /api/v1/config/ |
10 | Get configuration |
WebSocket Endpoints
| Endpoint | Description |
|---|---|
/ws/hub |
Real-time hub events (joins, parts, chat) |
/ws/logs |
Real-time log streaming |
Web Dashboard
Access the dashboard at http://localhost:8000/dashboard/
Pages
- Dashboard - Hub overview with stats and quick actions
- Users - Online and registered user management
- Bans - Ban list and management
- Logs - Real-time log viewer
- Console - Command execution interface
- Config - Hub configuration (Master only)
- Plugins - Plugin management (Admin only)
NMDCpb Protocol Extension
verlihub-py ships the server side of NMDCpb — a protobuf-based structured
messaging layer that extends classic NMDC with six integrated features. The hub
negotiates NMDCpb in $Supports, dispatches $PB/$PBR envelopes to a Python
plugin, and transparently translates to legacy NMDC ($<nick>, $To:, $Search)
for non-NMDCpb clients.
| Extension | Capability |
|---|---|
| NMDCpb | Protobuf message dispatch, legacy translation, feature negotiation |
| HubRelay | Hub-brokered relay sessions for encrypted, NAT-friendly transfers |
| E2EPM | End-to-end encrypted private messages with key-exchange forwarding |
| MediaShare | Media storage (filesystem/S3), HTTP upload/download API, P2P routing |
| Channels | Channel lifecycle, membership, message routing, E2E sender keys |
| VoiceVideo | 1:1 and group call signaling, hub streams, SFU fan-out |
Admin surface
- Chat commands (operator, class ≥ 5):
+nmdcpb stats,+nmdcpb users,+nmdcpb relay,+nmdcpb channel list|create|delete|info - REST API under
/dashboard/nmdcpb/api(admin JWT,user_class ≥ 5):GET /api/stats,GET /api/users,GET /api/relays,GET /api/relay/{id},POST /api/relay/{id}/close,POST /api/relay/close-all,POST /api/relay/close-user/{nick} - Media API mounted at
/api/media/(per-user HMAC bearer tokens):POST /upload,GET /quota,GET /{id},GET /{id}/thumb,GET /{id}/meta,DELETE /{id} - WebSocket
/ws/relaystreamsrelay_created/relay_closedevents - Dashboard at
/dashboard/nmdcpb/with live stats, relay/user tables, and admin actions
Client library
A high-level Python client for these extensions (E2E-encrypted PM, hub-relayed
transfers, media sharing, channels) ships in verlihub.client.nmdcpb — see
NMDCpb Client Library
below.
Detailed documentation
| Document | Contents |
|---|---|
| NMDCPB_PROTOCOL.md | Wire format, envelope types, feature negotiation |
| NMDCPB_IMPLEMENTATION.md | Hub plugin architecture, message flow, storage backends |
| NMDCPB_ADMIN_GUIDE.md | Commands, REST/WebSocket API, dashboard, config, troubleshooting |
| NMDCPB_PROTOCOL_WORKFLOWS.md | End-to-end sequence walkthroughs for every extension |
LLM & MCP Integration
verlihub-py includes optional LLM integration that connects to any OpenAI-compatible backend (Ollama, vLLM, llama.cpp, LiteLLM, OpenRouter, or a hosted API):
- AI Chat Assistant — a dashboard chat tab (
POST /api/v1/llm/chat, streaming over/ws/llm-chat) where admins ask natural-language questions and the LLM executes hub tool-calls (list users, kick, ban, read stats) and feeds results back for a final answer. - NMDC
Hub-SecurityBot — hub users chat with an LLM-backed bot via PM or main chat, with session memory, a mood engine, web access (search/fetch/RSS), and persistent notes. - MCP Server — a Model Context Protocol
server exposing the hub as tools/resources/prompts to AI editors (VS Code,
Claude Desktop) over stdio or HTTP; ships the
verlihub-mcpCLI.
Enable it in config and point base_url at your backend. See
LLM_INTEGRATION.md for the full architecture,
configuration reference, setup guides (Ollama/vLLM/llama.cpp), the tool-calling
flow, bot features, and MCP server/client usage.
Performance Benchmarks
The benchmark suite measures API performance including latency percentiles and throughput.
Running Benchmarks
# Quick health check
verlihub-bench quick
# Full API benchmark suite
verlihub-bench api --requests 1000 --concurrency 20
# Stress test
verlihub-bench stress --requests 5000 --concurrency 50
# Detailed latency profile
verlihub-bench latency --endpoint /api/v1/hub/stats --samples 1000
# Full benchmark with all tests
verlihub-bench full --stress --websocket --output results.json
Benchmark Options
--url, -u API base URL (default: http://localhost:8000)
--requests, -n Requests per benchmark (default: 100)
--concurrency, -c Concurrent connections (default: 10)
--output, -o Output file for results (JSON)
--token, -t Authentication token
--username Username for auth
--password Password for auth
Sample Output
======================================================================
Benchmark: GET /api/v1/hub/stats
======================================================================
Summary:
Total Requests: 1,000
Successful: 1,000 (100.0%)
Failed: 0
Total Time: 2.34s
Throughput: 427.35 req/s
Latency (ms):
Min: 1.234
Max: 45.678
Avg: 2.341
Std Dev: 1.567
p50 (median): 2.123
p95: 4.567
p99: 8.901
======================================================================
Programmatic Usage
import asyncio
from verlihub.benchmarks import BenchmarkRunner, BenchmarkSuite
async def run_benchmarks():
# Create a custom benchmark suite
suite = BenchmarkSuite("My Benchmarks")
suite.add_endpoint("Health", "GET", "/health", num_requests=500)
suite.add_endpoint("Stats", "GET", "/api/v1/hub/stats", num_requests=500)
# Run benchmarks
results = await suite.run(base_url="http://localhost:8000")
# Print summary
print(suite.summary())
# Export to JSON
with open("results.json", "w") as f:
f.write(suite.to_json())
asyncio.run(run_benchmarks())
Client Library
Synchronous Client
from verlihub.client import HubClient
client = HubClient("http://localhost:8000")
client.login("admin", "password")
# Get hub stats
stats = client.get_stats()
print(f"Users online: {stats['user_count']}")
# List online users
users = client.get_online_users()
for user in users:
print(f" {user['nick']} - {user['share']}")
# Kick a user
client.kick_user("baduser", reason="Spamming")
Asynchronous Client
import asyncio
from verlihub.client import AsyncHubClient
async def main():
async with AsyncHubClient("http://localhost:8000") as client:
await client.login("admin", "password")
stats = await client.get_stats()
print(stats)
asyncio.run(main())
NMDC Protocol Client
from verlihub.client import NMDCClient
# Connect directly to hub via NMDC protocol
client = NMDCClient("192.168.1.100", 4111)
client.connect("BotNick", "password")
# Send a message
client.send_chat("Hello from Python!")
# Get user list
users = client.get_users()
client.disconnect()
NMDCpb Client Library (E2EPM · HubRelay · MediaShare · Channels)
Beyond the raw protocol, verlihub-py ships a high-level NMDCpb client
(verlihub.client.nmdcpb) that speaks the protobuf overlay and exposes
ergonomic, strongly-typed APIs for the extension features. It doubles as the
reference client that validates the hub-side implementation. Requires the
protobuf + cryptography extras.
from verlihub.client import NMDCpbClient # also: WireCodec, E2EPMSession, E2EPMManager
client = NMDCpbClient("mybot", "password")
await client.connect("nmdc://hub.example.com:411")
# Structured chat / PM (protobuf)
await client.send_pb_chat("Hello from protobuf!")
await client.send_pb_pm("Alice", "Hi Alice")
End-to-end encrypted PM (E2EPM)
X25519 key exchange + ChaCha20-Poly1305, with 4-emoji verification fingerprints and Trust-On-First-Use key continuity — negotiated automatically on first use:
client.on_e2epm_established = lambda peer, fp: print(f"Secure with {peer}: {fp}")
client.on_encrypted_pm = lambda frm, text, enc: print(f"[E2E] {frm}: {text}")
await client.send_encrypted_pm("Alice", "Secret message")
Lower-level session control is available via E2EPMManager / E2EPMSession
(initiate_session, handle_key_exchange, encrypt_message,
decrypt_message).
Hub-relayed transfers (HubRelay)
Hub-brokered, NAT-friendly, resumable file relay with SHA-256 verification:
from verlihub.client.nmdcpb.relay import RelayFileTransfer
relay = RelayFileTransfer(client, download_dir="/downloads")
info = await relay.send_file("Alice", "/path/to/file.bin") # -> TransferInfo (progress, speed, state)
# …or drive the protocol directly:
client.on_relay_request = lambda frm, token, purpose, size: None
await client.accept_relay(token)
await client.send_relay_data(relay_id, chunk, offset)
await client.close_relay(relay_id)
client.relay_only_mode = True # privacy: force all transfers through the hub relay
Admin REST surface (dashboard, user_class ≥ 5) at /dashboard/nmdcpb/api:
GET /relays, GET /relay/{id}, POST /relay/{id}/close,
POST /relay/close-all, POST /relay/close-user/{nick}; live events over
the /ws/relay WebSocket (relay_created / relay_closed).
Media sharing (MediaShare)
Server-side storage with per-user quota, TTL, thumbnails, and a REST surface:
from verlihub.client.nmdcpb.media_storage import MediaStorage, MediaConfig
store = MediaStorage(MediaConfig())
meta = store.store(data, "clip.mp4", "video/mp4", uploader="mybot") # -> MediaMeta
quota = store.get_quota("mybot")
REST API (per-user HMAC bearer tokens), mounted at /api/media:
| Endpoint | Description |
|---|---|
POST /api/media/upload |
Upload a file (multipart) |
GET /api/media/{id} |
Download the file |
GET /api/media/{id}/thumb |
Download the thumbnail |
GET /api/media/{id}/meta |
Metadata JSON |
GET /api/media/quota |
Per-user quota |
DELETE /api/media/{id} |
Delete (owner or admin) |
Channels
Server-managed public/private channels with member roles
(MEMBER/ADMIN/OWNER/READONLY), message history, and group
sender-key encryption. Managed by
verlihub.client.nmdcpb.channel_manager.ChannelManager (auto-creates and
auto-joins #general); driven over the protobuf protocol with actions:
list / create / delete / join / leave / set-topic / kick / set-role.
Protobuf message types
All wire types are importable for advanced/manual use:
from verlihub.client.nmdcpb.nmdcpb_pb2 import (
PbEnvelope,
PbPMKeyExchange, PbEncryptedPM, PbPMPlaintext, # E2EPM
PbMediaUpload, PbMediaMeta, PbMediaRef, # MediaShare
PbRelayRequest, PbRelayAck, PbRelayData, PbRelayClosed, # HubRelay
PbChannel, PbChannelList, PbChannelMemberUpdate, # Channels
)
Configuration
Environment Variables
| Variable | Description | Default |
|---|---|---|
VH_API_HOST |
API bind host | 0.0.0.0 |
VH_API_PORT |
API bind port | 8000 |
VH_DB_HOST |
Database host | localhost |
VH_DB_PORT |
Database port | 3306 |
VH_DB_NAME |
Database name | verlihub |
VH_DB_USER |
Database user | verlihub |
VH_DB_PASS |
Database password | - |
VH_JWT_SECRET |
JWT signing key | (auto-generated) |
VH_JWT_EXPIRE_MINUTES |
Token expiration | 60 |
Database
The API supports both MySQL and SQLite:
# MySQL (production)
from verlihub.models.database import DatabaseConfig
config = DatabaseConfig(
driver="mysql",
host="localhost",
port=3306,
database="verlihub",
username="verlihub",
password="secret",
)
# SQLite (testing)
config = DatabaseConfig(
driver="sqlite",
database=":memory:", # or path to file
)
Testing
# Run all tests
pytest
# Run with coverage
pytest --cov=verlihub --cov-report=html
# Run specific test file
pytest tests/test_api_endpoints.py -v
# Run benchmark tests
pytest tests/test_benchmarks.py -v
Test Results
Current test status: 188 passed, 21 skipped
Skipped tests require C++ SWIG bindings to be built.
Development
Project Structure
python/
├── verlihub/
│ ├── api/ # FastAPI routes and app
│ ├── dashboard/ # Web dashboard templates
│ ├── client/ # Remote client library
│ ├── models/ # SQLModel database models
│ ├── benchmarks/ # Performance testing
│ └── cli.py # Command-line interface
├── tests/ # Test suite
└── pyproject.toml # Project configuration
Adding New Endpoints
- Create route in
verlihub/api/routes/ - Add to router in
verlihub/api/__init__.py - Add tests in
tests/test_api_endpoints.py - Update API documentation
Adding Dashboard Pages
- Create template in
verlihub/dashboard/templates/ - Add route in
verlihub/dashboard/routes.py - Add navigation link in
base.html - Add tests in
tests/test_dashboard.py
License
GPL-3.0-or-later - See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file verlihub_py-1.7.0.0.tar.gz.
File metadata
- Download URL: verlihub_py-1.7.0.0.tar.gz
- Upload date:
- Size: 2.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
662aa7dccc8db918332999341d01bf27ff96547657ac7645ea23b802c266a2b9
|
|
| MD5 |
63daa94083dc0f320e4cdf4f54ff7771
|
|
| BLAKE2b-256 |
e0670d40f90aec93081c5520b4556c1de6b0d53781c93d7604fe471bd2d418c7
|
Provenance
The following attestation bundles were made for verlihub_py-1.7.0.0.tar.gz:
Publisher:
wheels.yml on transfix/verlihub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
verlihub_py-1.7.0.0.tar.gz -
Subject digest:
662aa7dccc8db918332999341d01bf27ff96547657ac7645ea23b802c266a2b9 - Sigstore transparency entry: 2065731264
- Sigstore integration time:
-
Permalink:
transfix/verlihub@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Branch / Tag:
refs/tags/v1.7.0.0 - Owner: https://github.com/transfix
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
wheels.yml@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Trigger Event:
push
-
Statement type:
File details
Details for the file verlihub_py-1.7.0.0-cp313-cp313-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: verlihub_py-1.7.0.0-cp313-cp313-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 16.5 MB
- Tags: CPython 3.13, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f3110dcf5b4de288eb07ea0a1897b3361a786c9fb6259a2c54385cdb76502a9
|
|
| MD5 |
78b2043c4d5a8574c6858c8923dd71a4
|
|
| BLAKE2b-256 |
2e1290990e552d05593da19896f064978f3af4e94dcc256f8b4d6c3ceaec3ee7
|
Provenance
The following attestation bundles were made for verlihub_py-1.7.0.0-cp313-cp313-manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on transfix/verlihub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
verlihub_py-1.7.0.0-cp313-cp313-manylinux_2_28_x86_64.whl -
Subject digest:
8f3110dcf5b4de288eb07ea0a1897b3361a786c9fb6259a2c54385cdb76502a9 - Sigstore transparency entry: 2065731351
- Sigstore integration time:
-
Permalink:
transfix/verlihub@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Branch / Tag:
refs/tags/v1.7.0.0 - Owner: https://github.com/transfix
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
wheels.yml@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Trigger Event:
push
-
Statement type:
File details
Details for the file verlihub_py-1.7.0.0-cp312-cp312-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: verlihub_py-1.7.0.0-cp312-cp312-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 16.5 MB
- Tags: CPython 3.12, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d05ae59fdac30873e0a04c806148de2033e80f9d997c7700aa894316d883082a
|
|
| MD5 |
0cb76609c625c5798b7a1dea5bce26f5
|
|
| BLAKE2b-256 |
c546f519568809c1295e3c6d1331ccd1afd79945fe405c9ce8741994f466588f
|
Provenance
The following attestation bundles were made for verlihub_py-1.7.0.0-cp312-cp312-manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on transfix/verlihub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
verlihub_py-1.7.0.0-cp312-cp312-manylinux_2_28_x86_64.whl -
Subject digest:
d05ae59fdac30873e0a04c806148de2033e80f9d997c7700aa894316d883082a - Sigstore transparency entry: 2065731465
- Sigstore integration time:
-
Permalink:
transfix/verlihub@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Branch / Tag:
refs/tags/v1.7.0.0 - Owner: https://github.com/transfix
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
wheels.yml@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Trigger Event:
push
-
Statement type:
File details
Details for the file verlihub_py-1.7.0.0-cp311-cp311-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: verlihub_py-1.7.0.0-cp311-cp311-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 16.5 MB
- Tags: CPython 3.11, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
16dbb9af2dee97a8d109a76b57ac72ec9c1d1db599c886f038975c5066f531a9
|
|
| MD5 |
58b71dfdad3b5432c185252005356d9a
|
|
| BLAKE2b-256 |
96715f5dc98c56b52d12faf91535c3f24c520fb70a97a8c98f769f814e2e6570
|
Provenance
The following attestation bundles were made for verlihub_py-1.7.0.0-cp311-cp311-manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on transfix/verlihub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
verlihub_py-1.7.0.0-cp311-cp311-manylinux_2_28_x86_64.whl -
Subject digest:
16dbb9af2dee97a8d109a76b57ac72ec9c1d1db599c886f038975c5066f531a9 - Sigstore transparency entry: 2065731576
- Sigstore integration time:
-
Permalink:
transfix/verlihub@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Branch / Tag:
refs/tags/v1.7.0.0 - Owner: https://github.com/transfix
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
wheels.yml@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Trigger Event:
push
-
Statement type:
File details
Details for the file verlihub_py-1.7.0.0-cp310-cp310-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: verlihub_py-1.7.0.0-cp310-cp310-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 16.5 MB
- Tags: CPython 3.10, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
059ef934ea68ca4a9023a8cb11cf0228518560b65e97652a6b1d2b5bcb45df10
|
|
| MD5 |
7ac17cfd3209bf1820e5db224b166751
|
|
| BLAKE2b-256 |
680c92eefba5da74691556c571b0b1fdf1ab45157895623027f2824892f1f8c5
|
Provenance
The following attestation bundles were made for verlihub_py-1.7.0.0-cp310-cp310-manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on transfix/verlihub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
verlihub_py-1.7.0.0-cp310-cp310-manylinux_2_28_x86_64.whl -
Subject digest:
059ef934ea68ca4a9023a8cb11cf0228518560b65e97652a6b1d2b5bcb45df10 - Sigstore transparency entry: 2065731665
- Sigstore integration time:
-
Permalink:
transfix/verlihub@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Branch / Tag:
refs/tags/v1.7.0.0 - Owner: https://github.com/transfix
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
wheels.yml@a9a656d97fab3e42a6faed4f2d1d99beb52d036a -
Trigger Event:
push
-
Statement type: