diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..585497f --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,17 @@ +{ + "permissions": { + "allow": [ + "Bash(git status:*)", + "Bash(git log:*)", + "Bash(git diff:*)", + "Bash(git branch:*)", + "Bash(ls:*)", + "Bash(find:*)", + "Bash(make lint:*)", + "Bash(make fmt:*)", + "Bash(pre-commit run:*)", + "Bash(uv run pytest:*)", + "Bash(uv run ruff:*)" + ] + } +} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 023a9bf..c0f23a3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,3 +17,11 @@ repos: args: [ --fix ] # Run the formatter. - id: ruff-format + +- repo: local + hooks: + - id: commit-msg-dco + name: DCO sign-off check + language: script + entry: scripts/hooks/commit-msg + stages: [commit-msg] diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f645ce3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,61 @@ +# plugins-adapter + +## Overview + +An Envoy external processor (ext-proc) for configuring and invoking guardrails +in an Envoy-based gateway like [MCP Gateway](https://github.com/kagenti/mcp-gateway). +Intercepts gRPC traffic and applies configurable plugins (e.g., NeMo Guardrails). + +## Repository Structure + +``` +plugins-adapter/ +├── src/ # Core server implementation (ext-proc gRPC server) +├── plugins/ # Plugin implementations +│ └── examples/ # Example plugins (nemocheck, etc.) +├── tests/ # Unit tests (pytest) +├── docs/ # Architecture, build, deployment docs +├── resources/ # Kubernetes manifests and config +├── proto-build.sh # Protobuf code generation script +├── ext-proc.yaml # Envoy ExtProc deployment manifest +└── filter.yaml # Envoy HTTP filter config +``` + +## Key Commands + +| Task | Command | +|------|---------| +| Lint + Format | `make lint` | +| Test | `uv run pytest tests/ -v` | +| Build image | `make build PLUGIN_DEPS=nemocheck` | +| Deploy to Kind | `make all PLUGIN_DEPS=nemocheck` | +| Build protobufs | `uv sync --group proto && ./proto-build.sh` | +| Run locally | `make dev-run-nemocheck` | + +## Code Style + +- Python 3.11+ with `uv` package manager +- Linter/formatter: `ruff` (config in `pyproject.toml`) +- Pre-commit hooks: `pre-commit install` +- Sign-off required: `git commit -s` + +## Plugin Development + +Plugins live in `plugins/`. Each plugin implements the `cpex` interface. +See `plugins/examples/` for reference implementations. + +Config in `resources/config/config.yaml`: +```yaml +plugins: + - name: my_plugin + path: ./plugins/my_plugin + enabled: true +``` + +## DCO Sign-Off (Mandatory) + +All commits must include a `Signed-off-by` trailer: + +```sh +git commit -s -m "feat: add feature" +``` diff --git a/scripts/hooks/commit-msg b/scripts/hooks/commit-msg new file mode 100755 index 0000000..0cc3c50 --- /dev/null +++ b/scripts/hooks/commit-msg @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# commit-msg hook: enforce DCO sign-off and block Co-Authored-By AI attribution +set -euo pipefail + +COMMIT_MSG_FILE="$1" +COMMIT_MSG=$(cat "$COMMIT_MSG_FILE") + +# Check for DCO sign-off +if ! grep -qE "^Signed-off-by: .+ <.+@.+>" "$COMMIT_MSG_FILE"; then + echo "ERROR: Commit message missing Signed-off-by trailer (DCO required)." + echo " Use: git commit -s" + exit 1 +fi + +# Block Co-Authored-By for AI (use Assisted-By instead) +if grep -qiE "^Co-[Aa]uthored-[Bb]y:.*claude|^Co-[Aa]uthored-[Bb]y:.*anthropic|^Co-[Aa]uthored-[Bb]y:.*openai|^Co-[Aa]uthored-[Bb]y:.*chatgpt" "$COMMIT_MSG_FILE"; then + echo "ERROR: Use 'Assisted-By' instead of 'Co-Authored-By' for AI attribution." + echo " Replace with: Assisted-By: Claude (Anthropic AI) " + exit 1 +fi + +exit 0