stacklok / stacklok/toolhive

Remove unused PermissionProfile from operator CRD

Open
#4,538 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

api breaking-change go kubernetes operator tech-debt
Dominant language
Go
Stars
2.2k
Forks
300
Avg merge
1d 15h
Merged PRs (30d)
184

Description

Summary

PermissionProfile exists in the MCPServer CRD but is dead code in the operator. The Kubernetes container runtime (pkg/container/kubernetes/client.go) explicitly ignores the permission profile parameter (_ *permissions.Profile with a // TODO comment). The operator README already documents it as (not implemented) and has the entire Permission Profiles documentation section commented out with the note: "not implemented; commenting out until a decision is made on removal".

This should be removed before the API stabilizes to avoid shipping a non-functional field that implies security guarantees it doesn't enforce.

Context

PermissionProfile works in the CLI/Docker paththv run enforces filesystem mounts, network mode, container capabilities, and egress proxy rules. But the operator never translates these into Kubernetes-native equivalents (SecurityContext, NetworkPolicy, volume restrictions). The plumbing exists (RunConfig builder receives the profile name, ConfigMap gets mounted) but nothing downstream acts on it.

What to remove

1. API types (cmd/thv-operator/api/v1alpha1/mcpserver_types.go)

Remove these type definitions entirely:

  • PermissionProfileRef struct (lines ~504-521)
  • PermissionProfileSpec struct (lines ~523-536)
  • NetworkPermissions struct (lines ~538-548)
  • OutboundNetworkPermissions struct (lines ~550-564)
  • PermissionProfileTypeBuiltin and PermissionProfileTypeConfigMap constants (lines ~476-481)

Remove the field from MCPServerSpec:

  • PermissionProfile *PermissionProfileRef field (lines ~215-217)
2. Controller logic (cmd/thv-operator/controllers/)

mcpserver_runconfig.go (~lines 165-182):
Remove the entire if m.Spec.PermissionProfile != nil block that calls runner.WithPermissionProfileNameOrPath().

mcpserver_controller.go (~lines 1168-1186):
Remove the ConfigMap volume mount logic for permission profiles (the block that checks m.Spec.PermissionProfile != nil && m.Spec.PermissionProfile.Type == PermissionProfileTypeConfigMap and adds a "permission-profile" volume mount to /etc/toolhive/profiles).

3. Generated code (cmd/thv-operator/api/v1alpha1/zz_generated.deepcopy.go)

After removing the types, run task gen — the deepcopy functions for NetworkPermissions, OutboundNetworkPermissions, PermissionProfileRef, and PermissionProfileSpec will be regenerated automatically (removed).

4. E2E tests (test/e2e/thv-operator/)

virtualmcp/memory_test.go (~line 79-82):
Remove the PermissionProfile field initialization from the test MCPServer spec.

5. Documentation

cmd/thv-operator/README.md:

  • Remove the permissionProfile row from the configuration table (line ~229)
  • Remove the commented-out Permission Profiles section (lines ~232-255)

docs/arch/02-core-concepts.md:

  • Remove permissionProfile references (lines ~142, ~739)

docs/arch/05-runconfig-and-permissions.md:

  • Remove/update references to permission profiles in operator context (lines ~30, ~376, ~632)

Auto-generated docs (will regenerate):

  • docs/operator/crd-api.md — run task crdref-gen after removing types
  • docs/server/swagger.json, docs/server/swagger.yaml, docs/server/docs.go — these reference the CLI's permission types, not the CRD types, so they should be unaffected
6. CRD manifests (cmd/thv-operator/config/crd/)

Run task gen after removing types — CRD YAML manifests will regenerate without the permissionProfile field and its nested schemas.

Verification steps

task gen              # Regenerate deepcopy, CRD manifests
task crdref-gen       # Regenerate CRD API docs
task lint-fix         # Fix any lint issues
task lint             # Verify clean
task test             # Unit tests pass
task build            # Builds successfully

Notes

  • The CLI-side permission profile types in pkg/permissions/ and pkg/runner/config_builder.go are not affected — those are used by thv run and work correctly with Docker. Do not touch them.
  • Any existing MCPServer resources with permissionProfile set will have that field silently dropped on the next apply after the CRD is updated. This is acceptable for a v1alpha1 API.
  • If permission enforcement is needed in the operator in the future, it should be reimplemented using Kubernetes-native primitives (SecurityContext, NetworkPolicy) rather than re-exposing Docker-specific concepts.

Generated with Claude Code

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with cmd/thv-operator/api/v1alpha1/mcpserver_types.go and the PermissionProfile references in cmd/thv-operator/controllers/, then inspect test/e2e/thv-operator/virtualmcp/memory_test.go and the listed documentation files. Run task gen and task crdref-gen after the removals, followed by task lint, task test, and task build. Done means the operator API, generated CRDs and docs, tests, and validation commands no longer contain the operator PermissionProfile field while CLI permission types remain unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, kubernetes
Domain
documentation, infrastructure
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.