diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..23e20fc --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,21 @@ +{ + "name": "complypack", + "displayName": "ComplyPack", + "version": "0.1.0", + "description": "Generate Rego policies from Gemara catalogs and extract assessment requirements via MCP server", + "author": { + "name": "ComplyTime Authors", + "url": "https://github.com/complytime" + }, + "homepage": "https://github.com/complytime/complypack", + "repository": "https://github.com/complytime/complypack", + "license": "Apache-2.0", + "keywords": [ + "compliance", + "rego", + "opa", + "gemara", + "policy", + "mcp" + ] +} diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json new file mode 100644 index 0000000..bbc1c40 --- /dev/null +++ b/.cursor-plugin/plugin.json @@ -0,0 +1,20 @@ +{ + "name": "complypack", + "displayName": "ComplyPack", + "version": "0.1.0", + "description": "Generate Rego policies from Gemara catalogs and extract assessment requirements via MCP server", + "author": { + "name": "ComplyTime Authors", + "url": "https://github.com/complytime" + }, + "repository": "https://github.com/complytime/complypack", + "license": "Apache-2.0", + "keywords": [ + "compliance", + "rego", + "opa", + "gemara", + "policy", + "mcp" + ] +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ffa7566 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +.git +.github +.complytime +.cursor +.opencode +docs +kb +skills +tests +acceptance +*.md +!LICENSE diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml new file mode 100644 index 0000000..e16cb9b --- /dev/null +++ b/.github/workflows/container.yml @@ -0,0 +1,61 @@ +name: Container Image + +on: + push: + tags: + - 'v*' + branches: + - main + +permissions: + contents: read + +jobs: + push: + uses: complytime/org-infra/.github/workflows/reusable_publish_ghcr.yml@e266be092e71ac9343fcd6d5cafc50402161981e # main + permissions: + contents: read + packages: write + actions: read + id-token: write + attestations: write + with: + component_name: complypack + containerfile_path: Containerfile + context_path: . + image_name: complytime/complypack + image_description: "ComplyPack MCP server for compliance policy generation" + platforms: linux/amd64,linux/arm64 + + scan: + needs: push + if: >- + always() + && needs.push.result == 'success' + && needs.push.outputs.image != '' + uses: complytime/org-infra/.github/workflows/reusable_trivy_image_scan.yml@e266be092e71ac9343fcd6d5cafc50402161981e # main + permissions: + contents: read + packages: write + security-events: write + id-token: write + with: + image_ref: ${{ needs.push.outputs.image }}:${{ needs.push.outputs.tag }} + image_digest: ${{ needs.push.outputs.digest }} + trivy_severity: HIGH,CRITICAL + + sign: + needs: [push, scan] + if: >- + always() + && needs.push.result == 'success' + uses: complytime/org-infra/.github/workflows/reusable_sign_and_verify.yml@e266be092e71ac9343fcd6d5cafc50402161981e # main + permissions: + contents: read + packages: write + id-token: write + with: + image_name: ${{ needs.push.outputs.image }} + digest: ${{ needs.push.outputs.digest }} + allowed_identity_regex: "https://github.com/complytime/org-infra(/.*)?$" + verify_vuln: ${{ needs.scan.result == 'success' }} diff --git a/.mcp.json b/.mcp.json deleted file mode 100644 index 4c1fac4..0000000 --- a/.mcp.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "mcpServers": { - "complypack": { - "command": "/tmp/complypack", - "args": ["mcp", "serve", "--config", "/tmp/mcp-test/complypack.yaml"] - } - } -} diff --git a/.mcp.json.example b/.mcp.json.example new file mode 100644 index 0000000..e8694a4 --- /dev/null +++ b/.mcp.json.example @@ -0,0 +1,12 @@ +{ + "mcpServers": { + "complypack": { + "command": "docker", + "args": ["run", "--rm", "-i", + "ghcr.io/complytime/complypack:VERSION", + "mcp", "serve", + "--source", "oci://YOUR_REGISTRY/gemara/YOUR_CATALOG:TAG", + "--schema", "YOUR_PLATFORM"] + } + } +} diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..3f2f055 --- /dev/null +++ b/Containerfile @@ -0,0 +1,17 @@ +FROM golang:1.26-alpine AS builder + +WORKDIR /build +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o complypack ./cmd/complypack + +FROM registry.access.redhat.com/ubi9-micro:9.6-4@sha256:b498b3ea26111ab4b81d65139f2ebd2ef9a2abb7a4588b7fdcc54889f95e9caa + +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt +COPY --from=builder /build/complypack /usr/local/bin/complypack + +ARG USER_UID=10001 +USER ${USER_UID} + +ENTRYPOINT ["complypack"] diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..b2326e9 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,107 @@ +# Installing ComplyPack + +ComplyPack is a plugin that provides a compliance policy generation skill and +an MCP server for working with Gemara catalogs. + +## Prerequisites + +- Docker or Podman (Fedora users: `sudo dnf install podman-docker`) + +## Claude Code + +Install from the marketplace: + +``` +/plugin install complypack@claude-plugins-official +``` + +The skill is auto-discovered. To configure the MCP server, create a +`.mcp.json` in your project: + +```json +{ + "mcpServers": { + "complypack": { + "command": "docker", + "args": ["run", "--rm", "-i", + "ghcr.io/complytime/complypack:latest", + "mcp", "serve", + "--source", "oci://your-registry/gemara/your-catalog:v1", + "--schema", "ci"] + } + } +} +``` + +Replace the `--source` and `--schema` values with your Gemara catalog +references and target platforms. + +### Multiple sources and schemas + +```json +"args": ["run", "--rm", "-i", + "ghcr.io/complytime/complypack:latest", + "mcp", "serve", + "--source", "oci://registry.example.com/gemara/controls:v1", + "--source", "oci://registry.example.com/gemara/guidance:v1", + "--schema", "ci=cue://cue.dev/x/githubactions@v0#Workflow", + "--schema", "kubernetes"] +``` + +### Plain HTTP registries (development) + +Use `oci+http://` for registries without TLS: + +```json +"--source", "oci+http://localhost:5001/gemara/controls:v1" +``` + +## OpenCode + +Add to your `opencode.json`: + +```json +{ + "mcpServers": { + "complypack": { + "command": "docker", + "args": ["run", "--rm", "-i", + "ghcr.io/complytime/complypack:latest", + "mcp", "serve", + "--source", "oci://your-registry/gemara/your-catalog:v1", + "--schema", "ci"] + } + } +} +``` + +## Using a config file (advanced) + +If you prefer YAML configuration, mount a `complypack.yaml`: + +```json +"args": ["run", "--rm", "-i", + "-v", "./complypack.yaml:/config/complypack.yaml:ro", + "ghcr.io/complytime/complypack:latest", + "mcp", "serve", + "--config", "/config/complypack.yaml"] +``` + +## Verifying the image + +Images include SLSA provenance and SBOM attestations. To verify: + +``` +gh attestation verify oci://ghcr.io/complytime/complypack:latest \ + --owner complytime +``` + +## Embedded schemas + +These platforms have built-in schemas (no `--schema source` needed): + +- `kubernetes` +- `terraform` +- `docker` +- `ansible` +- `ci` diff --git a/cmd/complypack/cli/mcp.go b/cmd/complypack/cli/mcp.go index e0656e1..98f38a3 100644 --- a/cmd/complypack/cli/mcp.go +++ b/cmd/complypack/cli/mcp.go @@ -7,7 +7,9 @@ import ( "log" "os" "path/filepath" + "strings" + "github.com/complytime/complypack/internal/config" "github.com/complytime/complypack/internal/mcp" mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp" "github.com/spf13/cobra" @@ -31,6 +33,8 @@ func mcpServeCmd() *cobra.Command { var ( configPath string cacheDir string + sources []string + schemas []string ) cmd := &cobra.Command{ @@ -45,6 +49,12 @@ specified in complypack.yaml. Example: complypack mcp serve --config complypack.yaml + # Or use flags directly (no config file needed): + complypack mcp serve \ + --source oci://ghcr.io/org/catalog:v1 \ + --schema kubernetes \ + --schema ci=cue://cue.dev/x/githubactions@v0#Workflow + The server runs until interrupted (Ctrl+C) or the client disconnects.`, RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -59,10 +69,20 @@ The server runs until interrupted (Ctrl+C) or the client disconnects.`, resolvedCacheDir = filepath.Join(homeDir, ".complypack", "cache") } - // Create MCP server + // Create MCP server options opts := &mcp.ServerOptions{ - ConfigPath: configPath, - CacheDir: resolvedCacheDir, + CacheDir: resolvedCacheDir, + } + + // If any CLI flags are present, build config from flags + if len(sources) > 0 || len(schemas) > 0 { + cfg, err := buildConfigFromFlags(sources, schemas) + if err != nil { + return fmt.Errorf("failed to build config from flags: %w", err) + } + opts.Config = cfg + } else { + opts.ConfigPath = configPath } server, err := mcp.NewServer(ctx, opts) @@ -82,6 +102,86 @@ The server runs until interrupted (Ctrl+C) or the client disconnects.`, cmd.Flags().StringVarP(&configPath, "config", "c", "complypack.yaml", "Path to complypack.yaml config file") cmd.Flags().StringVar(&cacheDir, "cache-dir", "", "Cache directory (default: $HOME/.complypack/cache)") + cmd.Flags().StringArrayVar(&sources, "source", nil, "Gemara OCI source (repeatable, e.g. oci://ghcr.io/org/catalog:v1)") + cmd.Flags().StringArrayVar(&schemas, "schema", nil, "Platform schema (repeatable, e.g. kubernetes or ci=cue://...)") return cmd } + +// buildConfigFromFlags creates a ComplyPackConfig from --source and --schema flag values. +func buildConfigFromFlags(sources, schemas []string) (*config.ComplyPackConfig, error) { + entries, err := parseSourceFlags(sources) + if err != nil { + return nil, err + } + + schemaRefs, err := parseSchemaFlags(schemas) + if err != nil { + return nil, err + } + + return &config.ComplyPackConfig{ + Gemara: config.GemaraConfig{Sources: entries}, + Schemas: schemaRefs, + }, nil +} + +// parseSourceFlags converts --source flag values into GemaraSourceEntry values. +// +// - oci://... -> GemaraSourceEntry{Source: "oci://...", PlainHTTP: false} +// - oci+http://... -> GemaraSourceEntry{Source: "oci://...", PlainHTTP: true} +func parseSourceFlags(sources []string) ([]config.GemaraSourceEntry, error) { + if len(sources) == 0 { + return nil, nil + } + + entries := make([]config.GemaraSourceEntry, 0, len(sources)) + for _, s := range sources { + if s == "" { + return nil, fmt.Errorf("empty source flag value") + } + + entry := config.GemaraSourceEntry{} + if strings.HasPrefix(s, "oci+http://") { + entry.Source = "oci://" + strings.TrimPrefix(s, "oci+http://") + entry.PlainHTTP = true + } else { + entry.Source = s + } + entries = append(entries, entry) + } + return entries, nil +} + +// parseSchemaFlags converts --schema flag values into SchemaRef values. +// +// - "kubernetes" -> SchemaRef{Platform: "kubernetes"} (embedded) +// - "ci=cue://cue.dev/x/actions@v0" -> SchemaRef{Platform: "ci", Source: "cue://..."} +func parseSchemaFlags(schemas []string) ([]config.SchemaRef, error) { + if len(schemas) == 0 { + return nil, nil + } + + refs := make([]config.SchemaRef, 0, len(schemas)) + for _, s := range schemas { + if s == "" { + return nil, fmt.Errorf("empty schema flag value") + } + + ref := config.SchemaRef{} + if idx := strings.IndexByte(s, '='); idx >= 0 { + ref.Platform = s[:idx] + ref.Source = s[idx+1:] + if ref.Platform == "" { + return nil, fmt.Errorf("empty platform name in schema flag %q", s) + } + if ref.Source == "" { + return nil, fmt.Errorf("empty source for platform %q in schema flag %q", ref.Platform, s) + } + } else { + ref.Platform = s + } + refs = append(refs, ref) + } + return refs, nil +} diff --git a/cmd/complypack/cli/mcp_test.go b/cmd/complypack/cli/mcp_test.go index 761765e..07ff047 100644 --- a/cmd/complypack/cli/mcp_test.go +++ b/cmd/complypack/cli/mcp_test.go @@ -1,17 +1,17 @@ // SPDX-License-Identifier: Apache-2.0 -package cli_test +package cli import ( "testing" - "github.com/complytime/complypack/cmd/complypack/cli" + "github.com/complytime/complypack/internal/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestMcpCommand(t *testing.T) { - root := cli.New() + root := New() // Find the mcp command mcpCmd, _, err := root.Find([]string{"mcp"}) @@ -29,4 +29,251 @@ func TestMcpCommand(t *testing.T) { flags := serveCmd.Flags() assert.NotNil(t, flags.Lookup("config"), "should have --config flag") assert.NotNil(t, flags.Lookup("cache-dir"), "should have --cache-dir flag") + assert.NotNil(t, flags.Lookup("source"), "should have --source flag") + assert.NotNil(t, flags.Lookup("schema"), "should have --schema flag") +} + +func TestParseSourceFlags(t *testing.T) { + tests := []struct { + name string + sources []string + want []config.GemaraSourceEntry + wantErr string + }{ + { + name: "single OCI source with TLS", + sources: []string{"oci://ghcr.io/org/catalog:v1"}, + want: []config.GemaraSourceEntry{ + {Source: "oci://ghcr.io/org/catalog:v1", PlainHTTP: false}, + }, + }, + { + name: "single OCI source with plain HTTP", + sources: []string{"oci+http://localhost:5000/catalog:v1"}, + want: []config.GemaraSourceEntry{ + {Source: "oci://localhost:5000/catalog:v1", PlainHTTP: true}, + }, + }, + { + name: "multiple mixed sources", + sources: []string{ + "oci://ghcr.io/org/catalog:v1", + "oci+http://localhost:5000/guidance:latest", + "oci://ghcr.io/org/policy:v2", + }, + want: []config.GemaraSourceEntry{ + {Source: "oci://ghcr.io/org/catalog:v1", PlainHTTP: false}, + {Source: "oci://localhost:5000/guidance:latest", PlainHTTP: true}, + {Source: "oci://ghcr.io/org/policy:v2", PlainHTTP: false}, + }, + }, + { + name: "empty source", + sources: []string{""}, + wantErr: "empty source flag value", + }, + { + name: "nil sources returns nil", + sources: nil, + want: nil, + }, + { + name: "empty slice returns nil", + sources: []string{}, + want: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseSourceFlags(tt.sources) + if tt.wantErr != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.wantErr) + return + } + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} + +func TestBuildConfigFromFlags(t *testing.T) { + tests := []struct { + name string + sources []string + schemas []string + want *config.ComplyPackConfig + wantErr string + }{ + { + name: "single source and schema", + sources: []string{"oci://ghcr.io/org/catalog:v1"}, + schemas: []string{"kubernetes"}, + want: &config.ComplyPackConfig{ + Gemara: config.GemaraConfig{ + Sources: []config.GemaraSourceEntry{ + {Source: "oci://ghcr.io/org/catalog:v1", PlainHTTP: false}, + }, + }, + Schemas: []config.SchemaRef{ + {Platform: "kubernetes"}, + }, + }, + }, + { + name: "multiple sources and schemas", + sources: []string{ + "oci://ghcr.io/org/catalog:v1", + "oci+http://localhost:5000/guidance:latest", + }, + schemas: []string{ + "kubernetes", + "ci=cue://cue.dev/x/githubactions@v0#Workflow", + }, + want: &config.ComplyPackConfig{ + Gemara: config.GemaraConfig{ + Sources: []config.GemaraSourceEntry{ + {Source: "oci://ghcr.io/org/catalog:v1", PlainHTTP: false}, + {Source: "oci://localhost:5000/guidance:latest", PlainHTTP: true}, + }, + }, + Schemas: []config.SchemaRef{ + {Platform: "kubernetes"}, + {Platform: "ci", Source: "cue://cue.dev/x/githubactions@v0#Workflow"}, + }, + }, + }, + { + name: "empty sources and schemas", + sources: nil, + schemas: nil, + want: &config.ComplyPackConfig{ + Gemara: config.GemaraConfig{ + Sources: nil, + }, + Schemas: nil, + }, + }, + { + name: "schema only without sources", + sources: nil, + schemas: []string{"kubernetes"}, + want: &config.ComplyPackConfig{ + Gemara: config.GemaraConfig{ + Sources: nil, + }, + Schemas: []config.SchemaRef{ + {Platform: "kubernetes"}, + }, + }, + }, + { + name: "invalid source", + sources: []string{""}, + schemas: []string{"kubernetes"}, + wantErr: "empty source flag value", + }, + { + name: "invalid schema", + sources: []string{"oci://ghcr.io/org/catalog:v1"}, + schemas: []string{""}, + wantErr: "empty schema flag value", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildConfigFromFlags(tt.sources, tt.schemas) + if tt.wantErr != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.wantErr) + return + } + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} + +func TestParseSchemaFlags(t *testing.T) { + tests := []struct { + name string + schemas []string + want []config.SchemaRef + wantErr string + }{ + { + name: "bare platform name uses embedded schema", + schemas: []string{"kubernetes"}, + want: []config.SchemaRef{ + {Platform: "kubernetes"}, + }, + }, + { + name: "platform with external CUE source", + schemas: []string{"ci=cue://cue.dev/x/githubactions@v0#Workflow"}, + want: []config.SchemaRef{ + {Platform: "ci", Source: "cue://cue.dev/x/githubactions@v0#Workflow"}, + }, + }, + { + name: "platform with HTTPS source", + schemas: []string{"terraform=https://example.com/schema.json"}, + want: []config.SchemaRef{ + {Platform: "terraform", Source: "https://example.com/schema.json"}, + }, + }, + { + name: "mixed embedded and external schemas", + schemas: []string{ + "kubernetes", + "ci=cue://cue.dev/x/githubactions@v0#Workflow", + "docker", + }, + want: []config.SchemaRef{ + {Platform: "kubernetes"}, + {Platform: "ci", Source: "cue://cue.dev/x/githubactions@v0#Workflow"}, + {Platform: "docker"}, + }, + }, + { + name: "empty schema", + schemas: []string{""}, + wantErr: "empty schema flag value", + }, + { + name: "empty platform in key=value", + schemas: []string{"=cue://something"}, + wantErr: "empty platform name", + }, + { + name: "empty source in key=value", + schemas: []string{"ci="}, + wantErr: "empty source for platform", + }, + { + name: "nil schemas returns nil", + schemas: nil, + want: nil, + }, + { + name: "empty slice returns nil", + schemas: []string{}, + want: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseSchemaFlags(tt.schemas) + if tt.wantErr != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.wantErr) + return + } + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } } diff --git a/gemini-extension.json b/gemini-extension.json new file mode 100644 index 0000000..554c82c --- /dev/null +++ b/gemini-extension.json @@ -0,0 +1,5 @@ +{ + "name": "complypack", + "description": "Generate Rego policies from Gemara catalogs and extract assessment requirements via MCP server", + "version": "0.1.0" +} diff --git a/internal/mcp/server.go b/internal/mcp/server.go index f930b9e..9a762db 100644 --- a/internal/mcp/server.go +++ b/internal/mcp/server.go @@ -31,8 +31,13 @@ type Server struct { // ServerOptions configures ComplyPack MCP server initialization. type ServerOptions struct { // ConfigPath is the path to complypack.yaml. + // Ignored when Config is set. ConfigPath string + // Config provides configuration directly, bypassing file loading. + // When set, ConfigPath is ignored. + Config *config.ComplyPackConfig + // OCIStore is the directory for OCI artifact caching. OCIStore string @@ -58,10 +63,16 @@ func NewServer(ctx context.Context, opts *ServerOptions) (*Server, error) { return nil, fmt.Errorf("ServerOptions cannot be nil") } - // Load config - cfg, err := config.LoadConfig(opts.ConfigPath) - if err != nil { - return nil, fmt.Errorf("failed to load config: %w", err) + // Load config: use provided config or load from file + var cfg *config.ComplyPackConfig + if opts.Config != nil { + cfg = opts.Config + } else { + var err error + cfg, err = config.LoadConfig(opts.ConfigPath) + if err != nil { + return nil, fmt.Errorf("failed to load config: %w", err) + } } if err := cfg.ValidateForMCP(); err != nil { return nil, fmt.Errorf("failed to load config: %w", err) diff --git a/skills/complypack/INSTALL.md b/skills/complypack/INSTALL.md deleted file mode 100644 index 30ed835..0000000 --- a/skills/complypack/INSTALL.md +++ /dev/null @@ -1,162 +0,0 @@ -# Installing the Gemara Policy Generation Skill - -This skill works with any AI agent that can: -- Read markdown documentation -- Access MCP servers or file-based catalogs -- Generate Rego code -- Write files to disk - -## Quick Install (Recommended) - -### Using OpenPackage (OPKG) - -**Prerequisites:** Package must be published to local registry first: - -```bash -cd /path/to/complypack/skills/generating-gemara-policies -opkg publish --local -``` - -**Install for Claude Code:** -```bash -cd /path/to/your/project -opkg install generating-gemara-policies --platforms claude -``` - -**Install for Cursor:** -```bash -opkg install generating-gemara-policies --platforms cursor -``` - -**Install for Windsurf:** -```bash -opkg install generating-gemara-policies --platforms windsurf -``` - -**Learn more:** [OpenPackage Documentation](https://github.com/enulus/OpenPackage) - -## Manual Installation by Platform - -### Claude Code (Anthropic) - -**Location:** `~/.claude/skills/generating-gemara-policies/` - -```bash -mkdir -p ~/.claude/skills/generating-gemara-policies -cp skills/generating-gemara-policies/SKILL.md ~/.claude/skills/generating-gemara-policies/ -``` - -Claude Code automatically discovers skills in `~/.claude/skills/`. - -**Verify:** -```bash -ls ~/.claude/skills/generating-gemara-policies/SKILL.md -``` - -### Cursor - -**Location:** `.cursor/skills/generating-gemara-policies/` (project-level) - -```bash -mkdir -p .cursor/skills/generating-gemara-policies -cp skills/generating-gemara-policies/SKILL.md .cursor/skills/generating-gemara-policies/ -``` - -May require explicit `@` mention: `@generating-gemara-policies` - -### Windsurf - -**Location:** `.windsurf/skills/generating-gemara-policies/` (project-level) - -```bash -mkdir -p .windsurf/skills/generating-gemara-policies -cp skills/generating-gemara-policies/SKILL.md .windsurf/skills/generating-gemara-policies/ -``` - -### Other AI Agents - -**For agents that support skill directories:** -Check your agent's documentation for the skills directory location, then copy `SKILL.md` there. - -**For web-based AI without skill auto-loading:** - -1. Copy skill content to your prompt -2. Prepend to request: - -``` -I have a skill for generating Rego policies from Gemara controls. - -[Paste SKILL.md content here] - -Now, using this skill: Generate a policy for AC-1 targeting Kubernetes using Conftest. -``` - -## Project-Level Installation - -To include this skill in your project for team sharing: - -```bash -cd /path/to/your/project - -# For Claude Code projects -mkdir -p .claude/skills -cp /path/to/complypack/skills/generating-gemara-policies/SKILL.md \ - .claude/skills/generating-gemara-policies/ - -# For Cursor projects -mkdir -p .cursor/skills -cp /path/to/complypack/skills/generating-gemara-policies/SKILL.md \ - .cursor/skills/generating-gemara-policies/ - -git add .claude/skills/ .cursor/skills/ -git commit -m "Add Gemara policy generation skill" -``` - -## Verification - -After installation, test the skill is accessible: - -**For agents with CLI:** -```bash - --help # Should show skills if supported -``` - -**For all agents:** -Ask the AI: -``` -Do you have access to a skill called "generating-gemara-policies"? -``` - -If yes, it should describe the skill's purpose. - -## Troubleshooting - -**Skill not found:** -- Check skill is in correct directory for your platform -- Verify SKILL.md has proper frontmatter (name, description) -- Restart the AI agent/IDE - -**Skill doesn't execute correctly:** -- Ensure MCP server is configured (for ComplyPack integration) -- Check agent has file write permissions -- Verify platform schemas are accessible - -## Updating the Skill - -When the skill is updated in the ComplyPack repo: - -```bash -cd /path/to/complypack -git pull - -# Re-copy to your platform's skills directory -cp skills/generating-gemara-policies/SKILL.md ~/.claude/skills/generating-gemara-policies/ -# or -cp skills/generating-gemara-policies/SKILL.md .cursor/skills/generating-gemara-policies/ -# etc. -``` - -Or use OpenPackage to update: -```bash -opkg update generating-gemara-policies -``` diff --git a/skills/complypack/skills/SKILL.md b/skills/complypack/SKILL.md similarity index 100% rename from skills/complypack/skills/SKILL.md rename to skills/complypack/SKILL.md diff --git a/skills/complypack/openpackage.yml b/skills/complypack/openpackage.yml deleted file mode 100644 index 911af55..0000000 --- a/skills/complypack/openpackage.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: complypack -version: 2.0.0 -type: skill -description: Generate policies from Gemara catalogs and extract assessment requirements with ComplyPack MCP server -author: Jennifer Power -license: Apache-2.0 - -repository: - type: git - url: https://github.com/complytime/complypack - -keywords: - - rego - - opa - - conftest - - gemara - - compliance - - policy - - kubernetes - - terraform - - docker - - complypack - -files: - - "skills/SKILL.md" - - "INSTALL.md" - - "mcp.jsonc"