Skip to main content

One-line, agent-led install for Storm commercial metering (qualified engineering results — generative CAD & simulation).

Reason this release was yanked:

client wire-contract mismatch; use ≥0.3.0

Project description

storm-billing

Dependency-free Python SDK and one-line, agent-led installer for Storm's commercial metering (qualified engineering results — generative CAD & simulation).

pip install storm-billing

This installs a storm CLI, an onboarding kit designed to be driven by your coding agent, and an optional typed SDK:

storm init                      # write the onboarding kit into your project
storm agent-guide               # runbook + interview the agent asks you
storm adapter inspect SAMPLE    # offline: propose a mapping for your own events
storm doctor                    # read-only config + reachability check
storm provision --plan          # transparent plan; --apply after you approve
storm verify                    # authorization smoke test

This wheel is onboarding and provisioning tooling. It does not need to become a runtime dependency of your product. In the customer-hosted topology a pilot deploys, raw telemetry stays in your own Kafka/MSK log and a digest-pinned Storm projector reads it; your product runtime makes one synchronous HTTPS call at operation submission, which you can make with whatever HTTP client you already have. If you want that call written out for you rather than typed, copy examples/control-client/storm_control_client.py — one file, standard library only.

Reach for the SDK (from storm_billing import StormClient) when you want the accelerators: Shape A event builders, canonical evidence attestation, batch receipts, deterministic fixtures.

Enterprise-safe by design: a plain PyPI install (no curl | sh), a pure-Python wheel with no install-time code, and no network or mutation until you explicitly run a storm command. See https://stormbilling.dev/docs/install for the full flow.


SDK reference

Integration boundary

The SDK emits raw workflow observations; it cannot declare a result qualified, billable, accepted, priced, or certified. Storm's versioned deterministic policy owns qualification.

The customer-facing meter is qualified_engineering_result. One contract catalog covers DESIGN_GENERATION and SIMULATION_ANALYSIS. A top-level customer operation earns at most once after terminal technical success, verified evidence, customer-visible availability inside the product, and a complexity class derived from locked inputs.

Resource telemetry such as tokens, model/tool calls, solver/GPU/CPU seconds, storage, retries, and cache hits is retained for cost and margin analysis. It does not directly set the customer price or create a statement line.

Compatibility high-throughput client — not the pilot path

StormEdgeClient belongs to the earlier Storm-managed data plane and to the throughput benchmarks. A customer-hosted pilot does not use it, and onboarding never configures it. It is retained and supported for deployments already on that topology; described here so the behaviour is documented, not to recommend it.

It preserves the same submission identity and encoded body across transient retries and does not make one remote request per event. The first production-shaped pilot instead keeps raw telemetry in the customer's Kafka/MSK log and runs Storm's digest-pinned projector in the customer account.

  • Embedded mode returns LOCAL_WAL after the local encrypted WAL durability boundary.
  • Agentless mode returns REMOTE_LOG only after the replicated log acknowledges the batch; a partition fails fast.
  • Durable acceptance does not mean the result qualified.

Batching support by itself is not a throughput claim. A retained AWS_PRODUCTION_LIKE run measured the replicated-ingress tier at 1,071,440 events/second over about 600 seconds for the 1-KiB profile with zero measured log loss; it did not prove real-time commercial-path completion at that rate.

import os

from storm_metering import (
    StormClient,
    StormEdgeClient,
    engineering_operation_started_event,
    engineering_resource_recorded_event,
    engineering_result_available_event,
    engineering_result_completed_event,
)

customer_id = "nova-propulsion"
customer_operation_id = "operation-wing-design-001"
work_item_id = "wing-design-001"
input_fingerprint = "a" * 64
result_content_hash = "b" * 64
complexity = {
    "domain": "aerospace",
    "fidelity": "HIGH_FIDELITY",
    "constraint_count": "180",
    "geometry_feature_count": "4200",
    "assembly_component_count": "240",
    "optimization_candidate_count": "1200",
    "required_evidence_level": "VERIFIED",
}
common = {
    "customer_id": customer_id,
    "customer_operation_id": customer_operation_id,
    "work_item_id": work_item_id,
}

events = [
    engineering_operation_started_event(
        **common,
        event_id="operation-wing-design-001-started",
        time="2026-07-19T18:00:00.000Z",
        commercial_intent="CUSTOMER_REQUESTED",
        result_type="DESIGN_GENERATION",
        input_fingerprint=input_fingerprint,
        declared_complexity_inputs=complexity,
        qualification_deadline_at="2026-07-20T18:00:00.000Z",
    ),
    engineering_resource_recorded_event(
        **common,
        event_id="operation-wing-design-001-gpu",
        time="2026-07-19T18:05:00.000Z",
        attempt_id="attempt-001",
        meter="gpu_seconds",
        quantity="720.000000",
        disposition="ORIGINAL",
    ),
    engineering_result_completed_event(
        **common,
        event_id="operation-wing-design-001-completed",
        time="2026-07-19T18:12:00.000Z",
        attempt_id="attempt-001",
        result_id="result-wing-design-001",
        result_content_hash=result_content_hash,
        input_fingerprint=input_fingerprint,
        result_type="DESIGN_GENERATION",
        terminal_state="SUCCEEDED",
        design_status="COMPLETE",
        requirements_satisfied=True,
        final_complexity_inputs=complexity,
        operation_started_at="2026-07-19T18:00:00.000Z",
        operation_completed_at="2026-07-19T18:12:00.000Z",
        evidence_refs=["verified-evidence-record-001"],
        tool_version="design-tool-2026.1",
    ),
    engineering_result_available_event(
        **common,
        event_id="operation-wing-design-001-available",
        time="2026-07-19T18:13:00.000Z",
        result_id="result-wing-design-001",
        result_content_hash=result_content_hash,
        availability="CUSTOMER_VISIBLE",
        result_reference="product://workbench/results/result-wing-design-001",
    ),
]

# Admission is a control-plane decision, not telemetry ingestion. Storm derives
# the price and reserves exact currency; the producer never supplies an amount.
control = StormClient(
    base_url=os.environ["STORM_CONTROL_PLANE_URL"],
    ingest_api_key=os.environ["STORM_TELEMETRY_API_KEY"],
    control_plane_api_key=os.environ["STORM_COMMERCIAL_API_KEY"],
)
admission = control.authorize_engineering_operation(events[0])
if not admission["allowed"]:
    raise RuntimeError(
        f"Engineering operation denied: {admission['reason']}"
    )

edge = StormEdgeClient(
    edge_url=os.environ["STORM_EDGE_URL"],
    edge_token=os.environ["STORM_EDGE_TOKEN"],
    # Prefer gzip for a regional/agentless hop; local sidecars may use "none".
    compression="gzip",
)
receipts = edge.submit_events(
    events,
    submission_id="operation-wing-design-001-workflow",
)

For SIMULATION_ANALYSIS, provide convergence_status, residual, and max_constraint_violation instead of design fields. A nonconvergent simulation cannot earn the commercial result.

Use StormClient separately for scoped control-plane operations: central operation authorization, reservation lookup, evidence, qualification explanations, statements, CSV download, exports, and settlement destinations. Admission denial (402) is returned as a typed decision; malformed, unauthorized, and unexpected responses still raise StormApiError. Bounded edge-lease allocation is an explicit experimental compatibility seam, not a first-pilot requirement. Legacy finalized-simulation and internal-cost helpers remain for the Postgres compatibility path; new high-throughput integrations should use the four workflow builders above.

Engineering artifacts stay in customer-owned systems. Send only immutable hashes, US-resident references, and evidence metadata.

The first deployment profile targets AWS us-west-2, but the SDK makes no assumption about your cloud. It depends only on Storm's HTTP contracts and does not embed an AWS dependency.

See docs/api-contract.md, docs/architecture/high-throughput-data-plane.md, https://stormbilling.dev/docs/data-plane, and openapi/storm-agent-api.openapi.json.

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

storm_billing-0.2.0.tar.gz (57.1 kB view details)

Uploaded Source

Built Distribution

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

storm_billing-0.2.0-py3-none-any.whl (65.2 kB view details)

Uploaded Python 3

File details

Details for the file storm_billing-0.2.0.tar.gz.

File metadata

  • Download URL: storm_billing-0.2.0.tar.gz
  • Upload date:
  • Size: 57.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for storm_billing-0.2.0.tar.gz
Algorithm Hash digest
SHA256 843f4fb23dc636b82e11f456543fb59f8837826374ff67389f3923c6492951c7
MD5 b4c1c74f4145957ba2a6af94098c6c3b
BLAKE2b-256 59d15b005d1a16cc5425f0630a789c9b773ae38f75ed1ccdf5346632232c08db

See more details on using hashes here.

File details

Details for the file storm_billing-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: storm_billing-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 65.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for storm_billing-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d40946e62e888797635da3ed8c93eae8dd9f5df5ed5aa00fe673eb99e4575152
MD5 40070b054c9d08fbe929e4056f8190bb
BLAKE2b-256 5390ca0532ad6da534f286b1a090bf49b2215d97ddc5ee98ee21f631677baa23

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