# Lifecycle Sidecar

A lightweight Kubernetes sidecar that monitors the main agent container and handles cleanup when the container exits with a specific exit code indicating idle shutdown.

## Purpose

User agent containers self-manage their lifecycle by:
1. Tracking their own activity (MCP calls, trigger status)
2. Exiting with code `42` when idle (no triggers + no recent activity)
3. Delegating deployment cleanup to this sidecar

The sidecar watches the main container and:
- On exit code `42`: Deletes the deployment (and optionally PVC)
- On any other exit code: Allows Kubernetes restart policy to handle it

## Architecture

```
┌─────────────────────────────────────────────────┐
│                    Pod                          │
│  ┌────────────────┐      ┌──────────────────┐  │
│  │ Agent Container│      │ Lifecycle Sidecar│  │
│  │                │      │                  │  │
│  │ - Track activity     │ - Monitor agent  │  │
│  │ - Track triggers     │ - Watch exit code│  │
│  │ - Exit 42 if idle    │ - Delete if 42   │  │
│  └────────────────┘      └──────────────────┘  │
│         │                         │             │
│         │ writes exit_code        │             │
│         └─────────►/var/run/agent/exit_code    │
│                                   │             │
└───────────────────────────────────┼─────────────┘
                                    │
                                    ▼ k8s API
                         ┌──────────────────────┐
                         │  Delete Deployment   │
                         │  (+ PVC if anonymous)│
                         └──────────────────────┘
```

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `NAMESPACE` | Yes | Kubernetes namespace (injected via downward API) |
| `DEPLOYMENT_NAME` | Yes | Name of the deployment to delete (from pod label) |
| `USER_TYPE` | No | User license tier: `anonymous`, `free`, `paid`, `enterprise` |
| `MAIN_CONTAINER_PID` | No | PID of main container (for precise monitoring) |

## Exit Code Contract

The agent container uses exit codes to signal intent:

| Exit Code | Meaning | Sidecar Action |
|-----------|---------|----------------|
| `42` | Clean idle shutdown | Delete deployment + optional PVC |
| Any other | Error or normal restart | Allow Kubernetes to restart |

## RBAC Requirements

The sidecar requires a ServiceAccount with permission to delete its own deployment:

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "delete"]
```

See `deploy/k8s/base/lifecycle-sidecar-rbac.yaml` for the full RBAC configuration.

## Building

```bash
docker build -t ghcr.io/dexorder/lifecycle-sidecar:latest .
docker push ghcr.io/dexorder/lifecycle-sidecar:latest
```

## Example Usage

See `deploy/k8s/base/agent-deployment-example.yaml` for a complete example of how to configure an agent deployment with the lifecycle sidecar.

## Security Considerations

1. **Self-delete only**: The sidecar can only delete the deployment it's part of (enforced by label matching in admission policy)
2. **Non-privileged**: Runs as non-root user (UID 1000)
3. **Minimal permissions**: Only has `get` and `delete` on deployments/PVCs in the sandboxes namespace
4. **No cross-namespace access**: Scoped to `sandbox` namespace only
5. **Crash-safe**: Only triggers cleanup on exit code 42, never on crashes
