Metadata-Version: 2.4
Name: speculynx
Version: 0.3.0
Summary: Local-first OpenAPI and Network Policy security CLI
Author: Sami-BUTRT
License-Expression: MIT
Project-URL: Homepage, https://github.com/Sami-BUTRT/speculynx-cli
Project-URL: Repository, https://github.com/Sami-BUTRT/speculynx-cli
Project-URL: Issues, https://github.com/Sami-BUTRT/speculynx-cli/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Testing
Requires-Python: <3.15,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer<1,>=0.12
Requires-Dist: PyYAML<7,>=6
Requires-Dist: httpx<1,>=0.27
Requires-Dist: fpdf2<3,>=2.7
Requires-Dist: keyring<26,>=25
Dynamic: license-file

# Speculynx CLI

Speculynx is a local-first Python/Typer security CLI for OpenAPI 3.0.x/3.1.x
analysis and declarative Network Policy review. Swagger 2.0, GraphQL, gRPC, and
SOAP are outside the OpenAPI scanner MVP scope.

OpenAPI and Network Policy input files are analyzed locally. Speculynx does not
send customer OpenAPI documents or Network Policy files to the backend. Free
static OpenAPI scans work without a license and without network access.

## Install

### Recommended on Debian and Ubuntu

`pipx` installs Speculynx in an isolated Python environment without changing
the system Python packages:

```bash
sudo apt update
sudo apt install -y pipx
pipx ensurepath
pipx install speculynx
speculynx --help
```

You may need to reopen your terminal after running `pipx ensurepath`. For an
immediate one-session setup, you can also run:

```bash
export PATH="$PATH:$HOME/.local/bin"
```

The export command is not required for every user or shell. Once `pipx` is
already installed, the generic installation command is:

```bash
pipx install speculynx
```

### Windows PowerShell

```powershell
py -m pip install --user pipx
py -m pipx ensurepath
pipx install speculynx
speculynx --help
```

### macOS

When `pipx` is already available on macOS, use:

```bash
pipx install speculynx
speculynx --help
```

This page does not prescribe a macOS package manager setup.

### Update or uninstall

```bash
pipx upgrade speculynx
pipx uninstall speculynx
```

### Local source checkout

For contributors working from a local checkout, a virtual environment
remains the supported development workflow:

```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e .
```

Verify the installation:

```bash
speculynx --help
speculynx scan --file openapi.yaml
```

Free static scans work immediately without a license or backend connection.
For Pro features, run `speculynx login`: the command prompts interactively
for the license key with hidden input, verifies it with the licensing
backend, and stores a valid key in the operating-system credential store.

After a package build, install the wheel locally:

```powershell
python -m pip install dist\speculynx-0.3.0-py3-none-any.whl
```

## Commands

```text
speculynx --help
speculynx --version
speculynx scan --file path\to\openapi.yaml
speculynx policy --help
speculynx login
speculynx info
speculynx logout
speculynx-sync --help
```

`login` verifies a Pro license key with:

```text
POST /v1/verify
Authorization: Bearer <license_key>
```

The key is stored with the operating-system credential store through
`keyring`. Legacy `~/.speculynx.json` files are ignored. `login` exits with a
nonzero status when verification or secure storage fails.

### Licensing backend for development and tests

Ordinary users do not need to configure the licensing backend. By default,
Speculynx verifies Pro licenses against the exact official origin
https://api.speculynx.dev.

Development and E2E environments can set `SPECULYNX_API_BASE_URL` only to
the exact official origin or to a local loopback backend. For example:

```powershell
$env:SPECULYNX_API_BASE_URL = "http://127.0.0.1:8000"
speculynx login
```

Only the exact hosts `localhost`, `127.0.0.1`, and `::1` are accepted as an
override, over HTTP or HTTPS. Third-party domains are refused even over
HTTPS. The value is a backend base URL: do not put a license key,
credentials, query string, fragment, or API path in it. Speculynx builds the
canonical `/v1/verify` endpoint, does not follow redirects, and does not
store this setting in keyring or a user configuration file. Never use a
production license key against a local development backend.

### Dashboard synchronization

`speculynx-sync` uploads only a versioned JSON audit result; it never uploads
the OpenAPI source file. The synchronization backend is restricted to the
official `https://api.speculynx.dev` origin or an explicit loopback origin for
local development. Third-party origins, credentials, query strings, fragments,
and API paths are rejected before the stored license is read. Redirects and
proxy environment variables are not followed for the synchronization request.

For a local development backend:

```powershell
$env:SPECULYNX_API_URL = "http://127.0.0.1:8000"
speculynx-sync --result speculynx-report.json --name api.yaml
```

## Network Policy

Speculynx 0.3.0 exposes the production-validated, export-only Network Policy
workflow:

```text
speculynx policy check
speculynx policy simulate
speculynx policy gate
speculynx policy render
speculynx policy dry-run
speculynx policy approve
```

The supported renderer profile is:

```text
linux-router-forward-stateful-v1
```

Example validation and export:

```bash
speculynx policy check --file policy.yaml
speculynx policy simulate \
  --file policy.yaml \
  --source ADMIN-01 \
  --destination SERVER-01 \
  --service https
speculynx policy render --file policy.yaml --output policy.nft
```

The Network Policy pipeline is fail-closed. Incomplete or ambiguous policy
state does not become implicit ALLOW, and non-renderable policy state does not
produce a partial firewall artifact presented as complete.

The client-ready scope is intentionally narrow: local policy consistency,
static simulation, baseline/candidate change impact, vendor-neutral IR,
nftables rendering for the profile above, exact dry-run, local human-review
evidence, and export of the reviewed artifact.

The CLI does **not** execute `nft`, connect to a firewall, apply rules, authorize
deployment, configure NAT/routing/interfaces, or provide other firewall-vendor
renderers. Local approver labels are not authenticated identities or digital
signatures. See `docs/network-policy/` for the complete contracts, threat model,
production-validation evidence, and explicit non-goals.

## Installation troubleshooting

- `speculynx` not found: activate the virtual environment or ensure its
  `Scripts` directory is in `PATH`; for a `pipx` install, reopen the terminal
  after `pipx ensurepath`.
- `pipx` not found on Debian/Ubuntu: install it with `sudo apt install -y pipx`,
  then run `pipx ensurepath`.
- Unsupported Python: install Python 3.10 through 3.14.
- File not found: verify the path passed to `--file`.
- Swagger 2.0 rejected: convert the document to OpenAPI 3.0 or 3.1.
- Pro feature refused: check the stored license with `speculynx info`, then use
  `speculynx login` again if needed.

## Free Scan

```bash
speculynx scan --file path\to\openapi.yaml
```

Free rules include:

- `KEY-EXP-01`: keys or tokens exposed in query parameters.
- `HTTP-001`: insecure `http://` server URLs.
- `AUTH-001`: missing documented authentication.
- `KEY-EXP-02`: rotation or lifetime undocumented for an API key explicitly
  described as static or durable.

Free scans are explicitly partial: they run the four rules above and list
the Pro rules that were not executed. A Free scan with no finding reports an
indeterminate global verdict; it is not a validation that the API is
secure. OpenAPI files stay local. License verification sends no OpenAPI
content to the licensing service.

## JSON and CI/CD

Use `--json` for a single machine-readable JSON document on stdout:

```bash
speculynx scan --file openapi.yaml --json
```

Schema `1.0` includes the tool and input versions, scan mode, coverage,
executed, skipped, and non-evaluated rule IDs, per-control statuses,
severity counts, findings, and verdict. Per-control statuses are:

- `PASS`: the control ran and detected no matching signal;
- `FAIL`: the control ran and detected a risk signal;
- `NOT_EVALUATED`: the control could not produce a reliable result;
- `ERROR`: the command or control failed before producing a security result.

`NOT_EVALUATED` controls are not findings and are counted as neither `PASS`
nor `FAIL`. When a stored Pro license cannot be verified because the
licensing service is unavailable or its response is unusable, Free controls
still run locally while Pro controls are listed as `NOT_EVALUATED`. With no
stored key, or after a confirmed invalid or expired license, Pro controls
remain skipped. Fatal input or command errors can exit without emitting a
JSON result.

These fields are additive within schema `1.0`; removing or renaming an
existing field requires a new schema version.

Use `--fail-on` with `critical`, `high`, `medium`, `low`, or `never` (the
backward-compatible default). A threshold blocks on that severity and
higher:

```bash
speculynx scan --file openapi.yaml --json --fail-on high > speculynx-report.json
```

Minimal GitHub Actions step:

```yaml
- name: Audit OpenAPI
  run: |
    speculynx scan \
      --file openapi.yaml \
      --json \
      --fail-on high \
      > speculynx-report.json
```

Exit codes:

- `0`: scan completed and no finding reached the configured threshold;
- `1`: at least one finding reached the threshold;
- `2`: invalid argument, missing file, invalid JSON/YAML, or unsupported
  OpenAPI version;
- `3`: unexpected internal rule failure;
- `4`: a Pro-only operation was explicitly requested but unavailable.

Exit `0` for a partial Free scan means only that no executed Free finding
met the threshold. Coverage remains partial in both text and JSON.

## Pro Scan

With a valid Pro license, `scan` also runs heuristic checks for patterns
such as BOLA, BFLA, sensitive data exposure, likely secrets in examples,
SSRF inputs, missing rate-limit documentation, and unclear API
inventory/versioning.

Pro findings are static analysis signals, not proof of runtime
vulnerabilities. They should be manually verified against backend
authorization, gateway, and infrastructure controls.

## PDF Export

PDF export is Pro-only:

```bash
speculynx scan --file path\to\openapi.yaml --export report.pdf
```

In Free mode the export is refused.

## Live Scan / DAST

`scan-live` is Pro-only and can send real HTTP requests to a target API. It
is safe-by-default:

- only GET requests are sent by default;
- POST, PUT, PATCH, and DELETE require `--allow-unsafe-methods`;
- `--yes` does not unlock unsafe methods by itself;
- `--dry-run` prints planned requests without sending HTTP traffic;
- `--insecure` must be explicitly provided to disable TLS verification.

Examples:

```bash
speculynx scan-live --file openapi.yaml --target https://api.example.com --dry-run
speculynx scan-live --file openapi.yaml --target https://api.example.com --yes
speculynx scan-live --file openapi.yaml --target https://api.example.com --yes --allow-unsafe-methods
```

Only run `scan-live` against systems you own or are explicitly authorized to
test.

## Development

```bash
python -m unittest discover -s tests -v
python -m build
```
