kapable-ops-sdk (0.1.2)

Published 2026-07-14 14:01:40 +00:00 by kapable

Installation

[registries.forgejo]
index = "sparse+" # Sparse index
# index = "" # Git

[net]
git-fetch-with-cli = true
cargo add kapable-ops-sdk@0.1.2 --registry forgejo

About this package

Operator-tier Rust SDK for the Kapable v2 platform — the trust-perimeter twin of kapable-sdk. Rejects customer API keys at construction.

kapable-ops-sdk

Operator-tier Rust SDK for the Kapable v2 platform — the trust-perimeter twin of the customer kapable-sdk crate, and the Rust mirror of @kapable/ops-sdk.

Version 0.1.0 — 10 operator modules, 111 Rust methods, kept at exact method parity with the TypeScript package (enforced by the TS test/parity.test.ts, which parses both languages' real source). Published to the Kapable Forgejo cargo registry (2026-06-09).

Install

One-time registry setup in .cargo/config.toml (project or ~/.cargo):

[registries.kapable]
index = "sparse+https://git.kapable.dev/api/packages/kapable/cargo/"

Then:

[dependencies]
kapable-ops-sdk = { registry = "kapable", version = "0.1" }

It wraps the operator / admin / service-token endpoints the customer SDK deliberately excludes — Berth, Foreman, kapable-host, kapable-gateway, harbor-admin, the kapable-data query proxy, Burrow tunnels, kapable-auth admin, and the billing/comms internal routes — mirroring the kapable (customer) vs kapable-ops (operator) CLI trust split.

The operator vs customer perimeter (the load-bearing invariant)

Rust constructors can't throw, so the operator/customer boundary is enforced via a fallible constructor: OpsClient::new(base_url, token) returns Result<Self, OpsError> and errors with OpsError::CustomerKeyRejected when handed a customer API key. An operator wrapper therefore cannot even be instantiated with a customer credential.

Token prefixes
Accepted kses_, sk_admin_, st_/st_ci_/st_deploy_/st_wh_/st_svc_, unrecognized/JWT-shaped
Rejected sk_live_ / sk_test_ / sk_org_

The SDK never enforces authorization — the server is the sole authority. Some modules layer an additional per-call header credential (Berth deploy-sync's Ed25519 X-Signature; billing/comms X-Internal-Token; auth admin x-api-key).

use kapable_ops_sdk::OpsClient;
use kapable_ops_sdk::data::QueryOptions;

# async fn example() -> Result<(), kapable_ops_sdk::OpsError> {
let ops = OpsClient::new("https://data.kapable.ai", "st_ci_...")?;

// data query proxy
let r = ops.data().query("kapable_platform", "SELECT id FROM orgs WHERE slug = $1",
    QueryOptions { params: vec![serde_json::json!("acme")], ..Default::default() }).await?;
println!("{} rows", r.row_count);

// Berth deploy control-plane
let berth = OpsClient::new("http://localhost:3100", "st_svc_...")?;
let binaries = berth.berth().list_binaries().await?;

// A customer key errors at construction:
assert!(OpsClient::new("https://data.kapable.ai", "sk_live_...").is_err());
# Ok(())
# }

Modules

Each module is reachable as ops.<module>().<method>(). Method names mirror the TS package (snake_case), and every method wraps the identical VERB path as its TS twin (asserted by the parity test).

Module Methods Service Operator surface
auth 14 kapable-auth ADMIN surface (org/app provision, SSO callbacks, beta gate, request metrics, launchpad admin)
berth 25 berth Deploy control-plane (binaries, deploy-sync, slots, reconcile, freeze, rollback, restart, canary/rollout)
billing 1 kapable-billing Internal billing-portal mint (X-Internal-Token)
burrow 4 burrow Tunnel REGISTRY
comms 2 kapable-comms Service-to-service internal routes (X-Internal-Token)
data 1 kapable-data DB query proxy
foreman 15 foreman CI job queue + recipe runner
gateway 6 kapable-gateway gateway_services CRUD + reconcile
harbor 23 harbor ADMIN/mutation surface (products, features, tiers, licenses, releases, org keypairs)
host 20 kapable-host Containers + blue-green deploy, snapshots, images, volumes
Total 111 10 services operator coverage 51.2%

harbor has no server-side RBAC and incomplete org-scoping (IDOR, IMP-1366). Safe here only because this client rejects customer keys at construction.

Security types — shared, not copied

Permission / TokenType / Scope / AuthRequirement are re-exported from the kapable-sdk crate's security module (a local path dependency), so the two crates share a single source of truth and cannot drift. This crate adds the operator-perimeter helpers: is_operator_token, OPS_ACCEPTED_TOKEN_TYPES, OPS_REJECTED_TOKEN_TYPES.

Build & test

cargo build
cargo test    # unit + wiremock integration tests + doctests

This crate is standalone (no Cargo workspace in platform/); cargo build works on its own.

Coverage, manifest, drift, and CHANGELOG

The coverage manifest, drift/phantom check, and per-module/coverage numbers are driven from the TypeScript package (single source of truth across both languages):

  • Coverage manifest: ../kapable-ops-sdk/coverage-manifest.json (cd ../kapable-ops-sdk && bun run generate-manifest).
  • Drift / phantom check: cd ../kapable-ops-sdk && bun run check-drift.
  • Cross-language parity test: ../kapable-ops-sdk/test/parity.test.ts parses this crate's src/<mod>/mod.rs and asserts the method set + each method's VERB path matches the TS twin.
  • CHANGELOG: ../kapable-ops-sdk/CHANGELOG.md covers both packages (they ship together at method parity).

Dependencies

ID Version
base64 ^0.22
chrono ^0.4
futures-util ^0.3
kapable-sdk ^0.8.3
reqwest ^0.12
serde ^1
serde_json ^1
thiserror ^2
tokio ^1
uuid ^1
tokio ^1
wiremock ^0.6
Details
Cargo
2026-07-14 14:01:40 +00:00
4
MIT
93 KiB
Assets (1)
Versions (3) View all
0.1.2 2026-07-14
0.1.1 2026-06-09
0.1.0 2026-06-09