Metadata-Version: 2.4
Name: conformis
Version: 0.1.0
Summary: Scan your codebase locally for EU AI Act compliance risk. Your code never leaves your machine.
Author-email: Conformis <hello@conformis.tech>
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://conformis.tech
Project-URL: Dashboard, https://conformis.tech/readiness
Project-URL: Repository, https://github.com/rezakermanian78/conformis-demo
Project-URL: Issues, https://github.com/rezakermanian78/conformis-demo/issues
Keywords: eu-ai-act,compliance,ai-governance,security
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: requests<3,>=2.31
Requires-Dist: rich<14,>=13.0

# conformis

Scan your codebase locally for EU AI Act compliance risk.

**Your code never leaves your machine.** `conformis` runs its AI/ML-usage
detector entirely on your filesystem and only ever transmits the *findings*
it produces (a file path, a line number, a library name, a one-line snippet,
and a short description) — never full source files, never your `.env`,
never git history or metadata.

## Install

```bash
pip install conformis
```

Or from a local checkout:

```bash
pip install ./cli
```

## Quickstart

```bash
# Set your Conformis user id once
export CONFORMIS_USER_ID=user_xxxxxxxx

# Scan the current directory
conformis scan

# Scan a specific path
conformis scan ./my-project

# See exactly what would be sent, without sending anything
conformis scan --dry-run

# Strip all code snippets before anything is transmitted
conformis scan --privacy-mode
```

Instead of an env var, you can persist your user id in `~/.conformis/config`:

```json
{ "user_id": "user_xxxxxxxx" }
```

The `CONFORMIS_USER_ID` environment variable always takes precedence over
this file. If neither is set, the CLI exits with a clear error before
scanning anything.

## What is (and isn't) transmitted

The scanner walks your codebase locally (Python, JS/TS, `package.json`) and
produces a list of findings. Before anything is sent over the network, the
CLI filters every finding down to exactly these fields:

| Field         | Description                                            |
|---------------|---------------------------------------------------------|
| `file`        | Path **relative to the scan root** (never absolute)      |
| `line`        | Line number of the match                                |
| `library`     | Detected AI/ML library or framework                     |
| `description` | Human-readable description of the finding               |
| `context`     | Enclosing function/class name, if any                   |
| `snippet`     | The single matched line — **empty in `--privacy-mode`** |

Nothing else ever leaves the machine: no absolute paths, no environment
variables, no `.git` metadata, no file contents beyond the one matched line
per finding. This is enforced in code (`conformis/payload.py`), not just
documented — every finding is passed through a field allowlist and a
path-sanitizer before it is serialized, and `--privacy-mode` empties every
snippet client-side before the payload is even built.

### Sample payload

This is the exact JSON body POSTed to `/api/scans/local` for a project with
a single OpenAI call in `chatbot.py` (also viewable yourself, with nothing
sent, via `conformis scan --dry-run`):

```json
{
  "project_name": "my-project",
  "files_scanned": 1,
  "files_with_ai": 1,
  "findings": [
    {
      "file": "chatbot.py",
      "line": 4,
      "library": "openai",
      "description": "Imports OpenAI API",
      "context": "",
      "snippet": "import openai"
    },
    {
      "file": "chatbot.py",
      "line": 9,
      "library": "openai",
      "description": "Possible model inference call: .create()",
      "context": "function ask",
      "snippet": "response = client.chat.completions.create(model=\"gpt-4\", messages=messages)"
    }
  ],
  "privacy_mode": false
}
```

With `--privacy-mode`, every `snippet` field above becomes `""`.

Findings are capped at 500 and each snippet at 2000 characters client-side
(matching the backend's own limits), so a very large repo truncates
predictably with a clear message instead of failing on the server.

## Command reference

### `conformis scan [PATH]`

Scans `PATH` (default: current directory) and submits findings to
Conformis.

| Flag                | Description                                                        |
|----------------------|--------------------------------------------------------------------|
| `--privacy-mode`     | Strip all snippets client-side before sending                      |
| `--project-name NAME`| Project name to record (default: directory name)                   |
| `--dry-run`          | Print the exact JSON payload that would be sent; send nothing      |
| `--json`             | Machine-readable output on stdout (for CI)                         |
| `--no-wait`          | Submit and exit immediately without polling for results            |
| `--fail-under N`     | Exit 1 if the compliance score is below `N` (default: 0)           |

Progress/status messages (the scanning spinner, submission confirmation,
polling status) are written to stderr, so stdout stays clean JSON when
`--json` or `--dry-run` is used — safe to pipe or redirect in CI.

### `conformis --version`

Prints the installed CLI version.

## CI usage

```yaml
- name: Conformis compliance scan
  env:
    CONFORMIS_USER_ID: ${{ secrets.CONFORMIS_USER_ID }}
  run: |
    pip install conformis
    conformis scan --json --fail-under 70
```

### Exit codes

| Code | Meaning                                              |
|------|-------------------------------------------------------|
| `0`  | Scan completed and compliance score >= `--fail-under` |
| `1`  | Scan completed but compliance score < `--fail-under`  |
| `2`  | Error (bad path, missing auth, network/API failure, or analysis timed out after 3 minutes) |

## How it works

1. **Scan** — `conformis` walks the target directory locally using the same
   AST-based detector as the Conformis backend (vendored, not imported, so
   the CLI installs standalone with no dependency on the backend package).
2. **Sanitize** — findings are filtered to the allowlisted fields above,
   paths are forced relative to the scan root, and size limits are enforced.
3. **Submit** — the findings-only payload is POSTed to
   `POST /api/scans/local`, which starts the same classification pipeline
   used for full ZIP uploads, just without ever receiving your source code.
4. **Poll** — the CLI polls `GET /api/scans/{id}/readiness` every 3 seconds
   (3 minute timeout) until the classification finishes.
5. **Report** — a compliance score, risk tier summary, and the top 3
   recommended actions are printed, along with a link to the full dashboard
   at `https://conformis.tech/readiness/{scan_id}`.
