Metadata-Version: 2.4
Name: lex-align
Version: 2.2.1
Summary: Enterprise governance platform for AI-generated code: legal, security, and architectural alignment
Project-URL: Homepage, https://github.com/dlfelps/lex-align
Project-URL: Documentation, https://dlfelps.github.io/lex-align/
Project-URL: Repository, https://github.com/dlfelps/lex-align
Project-URL: Issues, https://github.com/dlfelps/lex-align/issues
Author-email: dlfelps <dlfelps@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: agents,ai,claude,compliance,cve,dependencies,governance,license,security,supply-chain
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Legal Industry
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.11
Requires-Dist: click>=8.0
Requires-Dist: httpx>=0.27
Requires-Dist: tomli-w>=1.0
Provides-Extra: server
Requires-Dist: aiosqlite>=0.20; extra == 'server'
Requires-Dist: click>=8.0; extra == 'server'
Requires-Dist: fastapi>=0.115; extra == 'server'
Requires-Dist: httpx>=0.27; extra == 'server'
Requires-Dist: jinja2>=3.1; extra == 'server'
Requires-Dist: pydantic-settings>=2.0; extra == 'server'
Requires-Dist: pydantic>=2.0; extra == 'server'
Requires-Dist: pyyaml>=6.0; extra == 'server'
Requires-Dist: redis>=5.0; extra == 'server'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'server'
Description-Content-Type: text/markdown

<p align="center">
  <img src="./lex-align-logo.png" alt="lex-align — Enterprise Governance Platform" width="520">
</p>

<h1 align="center">lex-align v2.2</h1>

<p align="center">
  <a href="https://dlfelps.github.io/lex-align/">Documentation</a> ·
  <a href="https://dlfelps.github.io/lex-align/for-agents/">For AI Agents</a> ·
  <a href="https://dlfelps.github.io/lex-align/llms.txt"><code>llms.txt</code></a>
</p>

Enterprise governance platform that ensures all code generated by AI agents or
developers is **legally compliant, architecturally sound, and secure**.

LexAlign moves governance from a reactive process to a proactive, collaborative
planning tool. It centralizes policy enforcement so compliance issues are
caught **before** code is committed, gives security and legal teams clear
intelligence into what AI agents are pulling into projects, and accelerates
development by steering agents toward a "golden path" of safe dependencies.

---

## Architecture

LexAlign 2.2 is a centralized client–server system:

| Component | Role |
|---|---|
| **`lex-align-server`** | Single source of truth. Holds the registry, runs license + CVE checks, persists the audit log, and surfaces report endpoints. Dockerized with Redis for caching. |
| **`lex-align-client`** | Thin, stateless CLI used by the AI agent and developers. Acts as both an **Advisor** (`check` / `request-approval`) and a **Guardrail** (git pre-commit hook + Claude Code hooks). |

### The "Use First, Approve in Parallel" principle

A new package that passes all automated checks (registry, CVE, license) is
considered **provisionally allowed** for immediate use. The agent does not
wait for human review — it adds the dependency, commits, and continues. In
parallel, `lex-align-client request-approval` submits the package for formal
inclusion in the registry. The human-review workflow runs asynchronously.

---

## Agent support

`lex-align`'s primary target is **[Claude Code]**. The hard guardrail —
the git pre-commit hook — is a vanilla Git hook that fires for any
agent (or human) committing to a governed repo, so the worst case for a
non-Claude agent is "denied dep blocked at commit time" rather than
"denied dep slips through". Soft guardrails (edit-time intercept,
auto-prompted advisor) are first-class for Claude Code only.

| Capability | [Claude Code] | [Cursor] | [Aider] |
|---|:---:|:---:|:---:|
| Git pre-commit guardrail (hard block on `DENIED`) | ✅ | ✅ | ✅ |
| `lex-align-client check` / `request-approval` CLI | ✅ | ✅ | ✅ |
| Edit-time `pyproject.toml` intercept | ✅ via `.claude/settings.json` `PreToolUse` | ❌ no equivalent hook | ❌ no equivalent hook |
| Auto-prompted to run `check` before adding a dep | ✅ via `CLAUDE.md` (written by `init`) | ⚠️ user-provided `.cursorrules` | ⚠️ user-provided `CONVENTIONS.md` |
| Auto-installed by `lex-align-client init` | ✅ hooks + `CLAUDE.md` | ❌ bring your own rules file | ❌ bring your own conventions file |

Other agents (Codex CLI, Windsurf, GitHub Copilot in VS Code, Cline, an
internal harness, a human at the terminal) get the pre-commit guardrail
and CLI commands for free. Broader native coverage (e.g. via MCP) is
not on the current roadmap.

See [Agent Support](https://dlfelps.github.io/lex-align/agent-support/)
for the full breakdown.

[Claude Code]: https://claude.com/claude-code
[Cursor]: https://cursor.com/
[Aider]: https://aider.chat/

---

## Quick start (single-user mode)

### 1. Run the server

```bash
pip install "lex-align[server]"
lex-align-server init                   # writes ./lexalign/ with compose stack + registry
cd lexalign
$EDITOR registry.yml                    # tune package policies (optional)
lex-align-server registry compile registry.yml registry.json
docker compose up -d
lex-align-server selftest               # confirms /api/v1/health responds
```

The server binds to `127.0.0.1:8765`. Redis is internal to the compose
network. Single-user mode (`AUTH_ENABLED=false`) is the default.

### 2. Initialize a project

```bash
pip install "lex-align"                 # or: uv add --dev "lex-align"
cd /path/to/your/project
lex-align-client init
```

`init` writes `.lexalign.toml`, installs the Claude Code session hooks under
`.claude/settings.json`, and adds a git pre-commit shim under
`.git/hooks/pre-commit`.

### 3. Use it

* **Plan-time advice:** `lex-align-client check --package httpx`
* **Async approval:** `lex-align-client request-approval --package httpx --rationale "standard async client"`
* **Pre-commit guardrail:** runs automatically on every `git commit`.
* **Claude Code:** the `PreToolUse` hook intercepts every edit to
  `pyproject.toml` and either allows, advises, or hard-blocks based on the
  server's verdict.

---

## What the server enforces

For every dependency the server is asked about, it runs three checks in order
and records the outcome to `audit_log` (SQLite):

| Check | Outcome |
|---|---|
| **Registry rule** | `preferred` / `version-constrained` allow; `approved` allows but flags `needs_rationale`; `deprecated` and `banned` deny. |
| **CVE check (OSV)** | Vulnerabilities with CVSS ≥ `cve_threshold * 10` (default 9.0, "critical") deny. Applies even to registry-`preferred` packages. |
| **License check (PyPI)** | For packages unknown to the registry, the license is fetched, normalized, and checked against `auto_approve_licenses` / `hard_ban_licenses`. |

Verdict labels returned to the client:

| Verdict | Meaning |
|---|---|
| `ALLOWED` | All checks passed; package is fully sanctioned. |
| `PROVISIONALLY_ALLOWED` | Unknown to registry but license + CVE passed. Eligible for `request-approval`. |
| `DENIED` | One of the checks blocked. The reason field explains which. |

---

## The enterprise registry

Authored as YAML and compiled to JSON via `lex-align-server registry compile`.
The bundled example (materialized as `registry.yml` by `lex-align-server init`):

```yaml
version: "1.2"
global_policies:
  auto_approve_licenses: [MIT, Apache-2.0, BSD-3-Clause]
  hard_ban_licenses: [AGPL-3.0, GPL-3.0, LGPL-3.0]
  unknown_license_policy: block
  cve_threshold: 0.9                  # 0–1 fraction of CVSS 10

packages:
  httpx:
    status: preferred
    reason: Standard async HTTP client.
  requests:
    status: deprecated
    replacement: httpx
  pyqt5:
    status: banned
    reason: GPL-licensed; no commercial license held.
  cryptography:
    status: version-constrained
    min_version: "42.0.0"
```

Mount the compiled `registry.json` into the server container at
`/etc/lexalign/registry.json` (the example compose file does this). Ship
updates by rebuilding the JSON, replacing the file, and restarting the
container.

---

## Server endpoints

All endpoints require an `X-LexAlign-Project: <name>` header. Single-user
mode trusts the project value as supplied; organization mode (Phase 3+) will
constrain it via the API key.

| Endpoint | Purpose |
|---|---|
| `GET /api/v1/evaluate?package=&version=` | Verdict for a single package. |
| `POST /api/v1/approval-requests` | Async submission of a registry-add request. Returns `202`. |
| `GET /api/v1/reports/legal` | Denials grouped under license category. |
| `GET /api/v1/reports/security` | Denials grouped under CVE category. |
| `GET /api/v1/reports/approval-requests` | Pending / approved / rejected list. |
| `GET /api/v1/reports/projects` | Per-project counts of evaluations and denials. |
| `GET /api/v1/health` | Liveness + readiness. |

Add `?project=<name>` to any report to scope it to a single project.

---

## Deployment modes

### Single-user (default)

* `AUTH_ENABLED=false`
* Bind to `127.0.0.1:8765`
* No API keys; every request is recorded as `requester="anonymous"`.

### Organization (Phase 3+ — flag wired, full implementation deferred)

* `AUTH_ENABLED=true`
* Bind to `0.0.0.0`, expose behind your reverse proxy.
* Bearer-token auth; keys minted via `lex-align-server admin keys generate`.
* Dashboards (`/dashboard/security`, `/dashboard/legal`, `/dashboard/registry`)
  enabled.

---

## Phase status

| Phase | Status |
|---|---|
| **1.** Server core (registry, license, CVE, audit, evaluate) | ✅ |
| **2.** Thin client (init, check, request-approval, pre-commit, Claude hooks) | ✅ |
| **3.** Approval workflow (persisted requests) and report endpoints | ✅ stubbed |
| **4.** Dashboards (skeleton HTML), PR-creation workflow, org-mode auth | 🟡 deferred |

The `request-approval` flow currently persists each request and logs a
`TODO: open PR for <pkg>` line. Real PR creation against the registry's git
repo lands in Phase 4.

---

## Repository layout

```
src/
  lex_align_client/                 # CLI + hooks
  lex_align_server/                 # FastAPI app
    _assets/                        # operator bundle (Dockerfile, compose,
                                    #   registry example, env) shipped in the
                                    #   wheel and emitted by `init`
tests/
  client/                           # 41 tests
  server/                           # 67 tests
```

Install for development:

```bash
uv sync --all-extras --all-groups
uv run pytest
```

---

## Privacy

The server is the only component that talks to the public internet — and
only to PyPI (license metadata) and OSV (CVE feed). The client only talks
to the configured server URL. The audit log lives on the server's host;
nothing is sent to a third party.
