# LockStock Enterprise Quick Start

This guide walks you through integrating LockStock compliance stamping into your AI agent or inference server.

## Prerequisites

- Python 3.10 or higher
- A provisioned LockStock agent (you'll have an `agent_id`, `genesis_token`, and `api_key`)
- Network access to `https://lockstock-api-i9kp.onrender.com`

## Step 1: Create a Virtual Environment

```bash
# Create and activate a virtual environment
python3 -m venv lockstock-env
source lockstock-env/bin/activate  # On Windows: lockstock-env\Scripts\activate

# Verify Python version
python --version  # Should be 3.10+
```

## Step 2: Install the Package

```bash
pip install lockstock-integrations==2.0.0rc2
```

Verify installation:
```bash
pip show lockstock-integrations
```

Expected output:
```
Name: lockstock-integrations
Version: 2.0.0rc2
...
```

## Step 3: Activate Your Agent

When you provision an agent on the dashboard, you receive:

| Credential | Format | Example |
|------------|--------|---------|
| `agent_id` | `agent_{hex}_{name}` | `agent_b3484fec_myagent` |
| `genesis_token` | 32-character string | `ce0mATQdt5keK1wEEUGgqIipl2vh7lKQ` |
| `api_key` | `lsk_admin_{hex}` | `lsk_admin_0f89affd...` |

**Before you can use the agent, you must activate it.** This initializes the cryptographic chain.

### One-Time Activation

Run this once per agent:

```python
import asyncio
from lockstock_core import LockStockClient

async def activate():
    client = LockStockClient(
        agent_id="YOUR_AGENT_ID",
        api_key="YOUR_API_KEY",
    )
    try:
        result = await client.activate(genesis_token="YOUR_GENESIS_TOKEN")
        print(f"Agent activated: {result['agent_id']}")
        print(f"Genesis hash: {result['genesis']['root_hash']}")
        print(f"Chain initialized at sequence 0")
    finally:
        await client.close()

asyncio.run(activate())
```

The client automatically generates a hardware fingerprint from your host environment (container ID, pod ID, hostname, MAC address). The genesis token is **burned after use** - you only need to do this once.

## Step 4: Configure Your Credentials

Store your `agent_id` and `api_key` securely. Common patterns:

**Environment variables (recommended):**
```bash
export LOCKSTOCK_AGENT_ID="agent_b3484fec_myagent"
export LOCKSTOCK_API_KEY="lsk_admin_0f89affd..."
```

**Or a `.env` file (with python-dotenv):**
```
LOCKSTOCK_AGENT_ID=agent_b3484fec_myagent
LOCKSTOCK_API_KEY=lsk_admin_0f89affd...
```

## Step 5: Basic Usage

### Minimal Example

```python
import asyncio
import os
from lockstock_core import LockStockClient

async def main():
    # Initialize client with your credentials
    client = LockStockClient(
        agent_id=os.environ["LOCKSTOCK_AGENT_ID"],
        api_key=os.environ["LOCKSTOCK_API_KEY"],
    )

    try:
        # Stamp a task (e.g., after completing an LLM inference)
        result = await client.stamp("chatcompletion")

        if result.authorized:
            print(f"Authorized! Sequence: {result.sequence}")
            print(f"State hash: {result.state_hash}")
        else:
            print(f"Denied: {result.reason}")

    finally:
        await client.close()

if __name__ == "__main__":
    asyncio.run(main())
```

### Using Context Manager (Recommended)

```python
import asyncio
import os
from lockstock_core import LockStockClient

async def main():
    async with LockStockClient(
        agent_id=os.environ["LOCKSTOCK_AGENT_ID"],
        api_key=os.environ["LOCKSTOCK_API_KEY"],
    ) as client:

        # Your AI task happens here
        # ... run inference, call tools, etc ...

        # Stamp the completed task
        result = await client.stamp("chatcompletion")

        if result.authorized:
            print(f"Stamped at sequence {result.sequence}")
        else:
            print(f"Stamp failed: {result.reason}")

asyncio.run(main())
```

## Step 6: Verify It Works

### Quick Verification Script

Save this as `verify_lockstock.py`:

```python
#!/usr/bin/env python3
"""Verify LockStock integration is working."""

import asyncio
import os
from lockstock_core import LockStockClient

async def verify():
    agent_id = os.environ.get("LOCKSTOCK_AGENT_ID")
    api_key = os.environ.get("LOCKSTOCK_API_KEY")

    if not agent_id or not api_key:
        print("ERROR: Set LOCKSTOCK_AGENT_ID and LOCKSTOCK_API_KEY environment variables")
        return False

    print(f"Agent ID: {agent_id}")
    print(f"API Key:  {api_key[:20]}...")
    print()

    async with LockStockClient(agent_id=agent_id, api_key=api_key) as client:
        # Step 1: Check current chain state
        print("1. Fetching current chain state...")
        state = await client.get_chain_state()

        if state is None:
            print("   ERROR: Could not fetch chain state. Check credentials.")
            return False

        initial_sequence = state["last_sequence"]
        print(f"   Current sequence: {initial_sequence}")
        print(f"   Last hash: {state['last_hash'][:32]}...")
        print()

        # Step 2: Stamp a heartbeat (low-privilege test task)
        print("2. Stamping a heartbeat task...")
        result = await client.stamp("heartbeat")

        if not result.authorized:
            print(f"   ERROR: Stamp rejected - {result.reason}")
            return False

        print(f"   Authorized: True")
        print(f"   New sequence: {result.sequence}")
        print(f"   State hash: {result.state_hash[:32]}...")
        print()

        # Step 3: Verify sequence advanced
        print("3. Verifying chain advanced...")
        new_state = await client.get_chain_state()
        final_sequence = new_state["last_sequence"]

        if final_sequence == initial_sequence + 1:
            print(f"   Sequence advanced: {initial_sequence} -> {final_sequence}")
            print()
            print("SUCCESS: LockStock integration is working correctly!")
            return True
        else:
            print(f"   ERROR: Sequence did not advance as expected")
            print(f"   Expected: {initial_sequence + 1}, Got: {final_sequence}")
            return False

if __name__ == "__main__":
    success = asyncio.run(verify())
    exit(0 if success else 1)
```

Run it:
```bash
python verify_lockstock.py
```

Expected output:
```
Agent ID: agent_b3484fec_myagent
API Key:  lsk_admin_0f89affd...

1. Fetching current chain state...
   Current sequence: 42
   Last hash: 9945b864e2a699810eab97ddd4297bca...

2. Stamping a heartbeat task...
   Authorized: True
   New sequence: 43
   State hash: e85ef80266bdec52c309fd9dbf7ed50f...

3. Verifying chain advanced...
   Sequence advanced: 42 -> 43

SUCCESS: LockStock integration is working correctly!
```

## Task Types

Use these task names with `client.stamp(task)`:

| Task | Use Case |
|------|----------|
| `chatcompletion` | LLM inference request |
| `chatcompletionresponse` | LLM inference response (for response stamping) |
| `network` | External API calls |
| `fileread` | Reading files |
| `filewrite` | Writing files |
| `shell` | Shell command execution |
| `database` | Database queries |
| `heartbeat` | Health checks, keep-alive |

## FastAPI Middleware Integration

For inference servers, use the thin middleware:

```python
from fastapi import FastAPI
from lockstock_fastapi import LockStockThinMiddleware

app = FastAPI()

app.add_middleware(
    LockStockThinMiddleware,
    agent_id="agent_xxx_myserver",
    api_key="lsk_admin_...",
    path_tasks={
        "/v1/chat/completions": "chatcompletion",
        "/v1/models": "network",
        "/health": None,  # Excluded from stamping
    },
)

@app.post("/v1/chat/completions")
async def chat_completions(request: dict):
    # Your inference logic here
    # Middleware automatically stamps before and after
    return {"choices": [...]}
```

## Troubleshooting

### "Could not fetch chain state"
- Verify your `agent_id` is correct (check dashboard)
- Verify your `api_key` is correct and not expired
- Check network connectivity to `https://lockstock-api-i9kp.onrender.com`

### "Stamp rejected"
- Check the `result.reason` field for details
- Common causes: agent revoked, capability not allowed, sequence mismatch

### Sequence mismatch (409 error)
- This means another client stamped using this agent
- Call `await client.sync()` to refresh local sequence tracking
- The client handles this automatically on next stamp

## Support

- Dashboard: Contact your LockStock administrator
- Documentation: See the full API reference in the package
- Issues: Report bugs to your support channel
