Metadata-Version: 2.4
Name: disposable-exec
Version: 0.2.1
Summary: Python SDK for disposable-exec — a control layer for short-lived Python execution
Project-URL: Homepage, https://disposable-exec.com
Project-URL: Source, https://github.com/DevBunny-exe/disposable-exec
Project-URL: Documentation, https://disposable-exec.com
Project-URL: Tracker, https://github.com/DevBunny-exe/disposable-exec/issues
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31.0
Requires-Dist: python-multipart>=0.0.9
Dynamic: description
Dynamic: description-content-type
Dynamic: license-file
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# disposable-exec

A control layer for the Python you didn't write.

- Website: https://disposable-exec.com
- Install: https://pypi.org/project/disposable-exec/
- Source: https://github.com/DevBunny-exe/disposable-exec

disposable-exec is a runtime for Python code whose origin isn't yours —
agent-generated, user-submitted, or third-party. Every run executes in a
fresh isolated container with no network access, a read-only root filesystem,
and a hard wall-clock timeout.

## Why use it

Sometimes you need to run Python that you do not want on your app host yet.

The real problem is uncertainty:
- What files does it try to touch?
- Does it make network requests?
- Does it fail halfway and leave junk behind?
- Do you really want that touching your machine or app host?

disposable-exec lets you run first, inspect first, and decide later.

Beyond isolation, you get a structured control layer:
- A **status lifecycle** with named phases (`queued`, `claimed`, `running`, `completed`, `failed`, `canceled`) and timestamps for each transition.
- A **cancel path** — stop a queued execution and get your credits back; for in-progress runs, the cancel request is accepted and applied as soon as possible.
- **Structured failure reasons** — `timeout`, `exit_nonzero`, `sandbox_error`, `platform_error`, `orphaned` — so you don't have to parse stderr to classify what went wrong.

## Good fit

Use disposable-exec when you want to:
- isolate risky Python execution
- add disposable execution to an automation tool
- give an AI agent code execution without exposing your app host
- cancel an execution you no longer want

## Quickstart

Install from PyPI:

```bash
pip install disposable-exec
```

Set your API credentials:

```bash
export DISPOSABLE_EXEC_BASE_URL="https://api.disposable-exec.com"
export DISPOSABLE_EXEC_API_KEY="YOUR_API_KEY"
```

Windows PowerShell:

```powershell
$env:DISPOSABLE_EXEC_BASE_URL="https://api.disposable-exec.com"
$env:DISPOSABLE_EXEC_API_KEY="YOUR_API_KEY"
```

### Minimal Python example

```python
from disposable_exec.client import Client

client = Client()

me = client.me()
print(me)

run_resp = client.run("print('hello from disposable-exec')")
execution_id = run_resp["execution_id"]

while True:
    status = client.status(execution_id)
    print(status)
    if status.get("status") in {"completed", "failed", "canceled"}:
        break

result = client.result(execution_id)
print(result)
```

## Core API flow

Typical flow:

1. `me()` - check credit/account state
2. `diagnose_script()` or `diagnose_files()` - optional cheap preflight layer
3. `run()` or `run_files()` - submit execution
4. `status(execution_id)` - poll execution state
5. `result(execution_id)` - fetch stdout/stderr/exit code
6. `cancel(execution_id)` - cancel a queued or in-progress execution

Canonical terminal states:
- `completed`
- `failed`
- `canceled`

## Client methods

Current Python client methods:

```python
from disposable_exec.client import Client
```

- `Client().me()`
- `Client().run(script)`
- `Client().run_files(entrypoint, files)`
- `Client().diagnose_script(script)`
- `Client().diagnose_files(entrypoint, files)`
- `Client().status(execution_id)`
- `Client().result(execution_id)`
- `Client().cancel(execution_id, reason=None)`

## Examples

### 1) Test a single script

```python
from disposable_exec.client import Client

client = Client()
resp = client.run("print('hello world')")
print(resp)
```

### 2) Diagnose a script before running it

```python
from disposable_exec.client import Client

client = Client()
diag = client.diagnose_script("print('hello from diagnose')")
print(diag)
```

### 3) Run multiple Python files

```python
from disposable_exec.client import Client

client = Client()

files = [
    {"path": "main.py", "content": "from utils import add\nprint(add(2, 2))"},
    {"path": "utils.py", "content": "def add(a, b):\n    return a + b"},
]

resp = client.run_files("main.py", files)
print(resp)
```

### 4) Agent / automation use case

If you are building an agent or automation system, disposable-exec can be the execution layer instead of letting tools run directly on your app host.

Use it when you want:
- isolated execution
- structured results and failure reasons
- lifecycle visibility
- a cancel path for executions you no longer need

### 5) Cancel a queued execution

```python
from disposable_exec.client import Client

client = Client()
resp = client.run("import time; time.sleep(30)")
cancel_resp = client.cancel(resp["execution_id"], reason="changed my mind")
print(cancel_resp)
```

## What's new in 0.2.1

- **Full cancel support**: `client.cancel(execution_id)` now works for all execution states. For running executions, the worker receives a cancel signal and performs `docker kill` to stop the container immediately. Previously, running cancels were accepted but the execution would finish naturally.
- **Billing history**: Portal users can now see their complete credit usage history — every execution, every refund, every diagnose call — in the Billing page.
- **Execution audit log**: The Usage page now shows a full execution history with status, duration, failure reason, and lifecycle timeline for each run. Supports pagination.

## What's new in 0.2.0

- **Cancel execution**: `client.cancel(execution_id)` stops a queued run and refunds credits. For claimed/running executions, the cancel request is accepted but the run may finish naturally (full docker-kill support is coming in a future release).
- **Structured failure reasons**: `/status` and `/result` responses now include a `failure_reason` field (`timeout`, `exit_nonzero`, `sandbox_error`, `platform_error`, `orphaned`) so you don't have to parse stderr to classify failures.
- **Execution timeline**: `/status` responses now include a `timeline` object with timestamps for each lifecycle phase (`queued_at`, `claimed_at`, `running_started_at`, `finished_at`, etc.).
- **New status values**: `canceling` (cancel in progress) and `canceled` (terminal, execution was stopped by user).

## Product positioning

disposable-exec is a control layer for short-lived Python execution.

It is not:
- long-lived compute
- arbitrary infrastructure hosting
- a full CI platform
- just another VPS
- a replacement for your main host

## Honest limits

disposable-exec is an execution boundary, not a complete trust story. This section
lists what you should **not** assume today.

### Isolation

- Isolation is provided by Docker with hardened flags (`--network=none`,
  `--read-only`, a `noexec` tmpfs, a 128 MB memory cap, a 0.5 CPU share, a
  64-process limit). This is container-level isolation, not microVM or
  VM-level isolation. If your threat model requires kernel-level separation
  between tenants, evaluate accordingly.
- Every execution runs in a fresh container. Containers do not share state
  with each other.

### Runtime limits

- Wall-clock timeout per execution: 30 seconds (server-enforced).
- Memory per execution: 128 MB hard cap.
- CPU per execution: 0.5 CPU share.
- Writable tmpfs per execution: 16 MB, `noexec`, `nosuid`.
- Network from inside the sandbox: fully disabled.
- Output size per execution: stdout + stderr truncated at ~64 KB each.

### Availability

- Currently operated as a single primary node. No automatic regional
  failover. A scheduled Redis externalization is documented but not
  executed.
- No published uptime SLA.

### Data

- Your submitted scripts, stdout, stderr, and execution metadata are
  retained on our infrastructure. There is no automated retention cutoff
  today. Deletion requests are handled manually via support.
- API keys are stored as SHA-256 hashes of a 192-bit random token. Raw
  keys are returned exactly once at creation.
- There is no customer-facing audit log export at this time.

### Security review

- disposable-exec has not undergone third-party security certification or
  penetration testing. There is no active bug bounty program.
- Security reports are welcome at the support email and will be
  acknowledged, though no formal response SLA is offered yet.

### Rate and abuse protection

- Per-key rate limits are enforced at the API layer.
- There is no WAF, CDN, or third-party DDoS mitigation in front of the API
  today.

We will update this section as limits change. If any of the above would
block your use case, let us know — we'd rather know before you commit than
find out after.

## Safety note

disposable-exec reduces the chance that unknown scripts touch your real machine directly. It does not mean every script is safe or that you should stop reviewing suspicious behavior. Isolation is the point, not blind trust.

## Pricing

Current plans:

- Free - 50 credits/month
- Starter - 3,000 credits/month
- Pro - 12,000 credits/month
- Scale - 40,000 credits/month

Runs and diagnostics consume credits based on request size. Stay on Free while validating the flow, and move to Starter when you need recurring usage or more monthly headroom.

Check the live website for current pricing and plan details.

## Links

- PyPI: https://pypi.org/project/disposable-exec/
- Website: https://disposable-exec.com
- GitHub: https://github.com/DevBunny-exe/disposable-exec

## Contact

For product questions or integration inquiries:

- devbunny.exe@gmail.com
