Metadata-Version: 2.4
Name: agent-opaque-env
Version: 0.4.0
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Rust
License-File: LICENSE
Summary: Self-describing encrypted env files for AI-assisted development
Keywords: env,secrets,ai-agent,rust
License-Expression: MIT
Requires-Python: >=3.11
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# agent-opaque-env

Self-describing encrypted environment files for AI-assisted development.

The package keeps environment keys and values out of plain-text repository context. Its Rust
extension also raises the cost of casual static analysis. It is not a secret manager: an agent or
process allowed to call `load_env()` can read the returned values.

## Install

```console
uv add agent-opaque-env
```

The wheel contains the Rust implementation. Users do not need to install `cryptography` or a Rust
toolchain when a wheel is available for their platform.

## Use

```python
from agent_opaque_env import dump_env, load_env


dump_env({"APP_MODE": "development"}, ".env")
values = load_env(".env")
```

`dump_env()` defaults to the zero-configuration `obfuscation` profile. It creates an owner-only
file and stores shuffled key material with the ciphertext. This prevents direct text collection but
does not create a separate secret boundary.

For protection when the repository is copied without its key, use the `protected` profile:

```python
from agent_opaque_env import dump_env, load_env


# Public example key only. Never use this key for real secrets.
key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
dump_env(values, ".env", profile="protected", key=key, key_id="example-local")
values = load_env(".env", key=key)
```

Generate a unique key for real use and keep it outside the repository. Instead of passing `key=`,
applications may set the `AGENT_OPAQUE_ENV_KEY` environment variable. Missing or incorrect keys fail
explicitly and never downgrade to `obfuscation`.

```python
from agent_opaque_env import generate_key


key = generate_key()  # Store this outside the repository before encrypting files.
```

## Self-describing AOE1 format

An AOE1 file is ASCII with exactly three lines:

```text
AGENT-OPAQUE-ENV/1
{"algorithm":"AES-256-GCM","format":"AOE1","import":"agent_opaque_env","loader":"load_env","package":"https://pypi.org/project/agent-opaque-env/","profile":"obfuscation"}
{"ciphertext":"...","key_fragments":["...","...","..."],"nonce":"..."}
```

The fixed `package` URL tells a developer or agent that the `agent-opaque-env` PyPI distribution and
its `load_env` API understand the file.
It never contains a shell command, package-manager arguments, any other URL, environment values, or
other executable instructions. Verify the dependency against the project configuration before
installing anything named by an untrusted file.

Metadata bytes are authenticated as AES-GCM associated data. Unknown fields, non-canonical JSON,
modified metadata, altered ciphertext, and unsupported formats are rejected.

## API

```python
dump_env(values, path=".env", *, profile="obfuscation", key=None, key_id=None)
load_env(path=".env", *, key=None) -> dict[str, str]
loads_env(data, *, key=None) -> dict[str, str]
generate_key() -> str
```

Only CPython 3.11 and newer are supported. New files use AOE1 exclusively; Pickle and older formats
are intentionally unsupported.

