Skip to content

Commit 520022d

Browse files
committed
add skill
Signed-off-by: Jose I. Paris <jiparis@chainloop.dev>
1 parent a720e2a commit 520022d

3 files changed

Lines changed: 79 additions & 88 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
name: custom-builtin-functions
3+
description: Create a custom builtin function to be used in the Rego policy engine
4+
---
5+
6+
### Policy Engine Extension
7+
8+
The OPA/Rego policy engine supports custom built-in functions written in Go.
9+
10+
**Adding Custom Built-ins**:
11+
12+
1. **Create Built-in Implementation** (e.g., `pkg/policies/engine/rego/builtins/myfeature.go`):
13+
```go
14+
package builtins
15+
16+
import (
17+
"github.com/open-policy-agent/opa/ast"
18+
"github.com/open-policy-agent/opa/topdown"
19+
"github.com/open-policy-agent/opa/types"
20+
)
21+
22+
const myFuncName = "chainloop.my_function"
23+
24+
func RegisterMyBuiltins() error {
25+
return Register(&ast.Builtin{
26+
Name: myFuncName,
27+
Description: "Description of what this function does",
28+
Decl: types.NewFunction(
29+
types.Args(types.Named("input", types.S).Description("this is the input")),
30+
types.Named("result", types.S).Description("this is the result"),
31+
),
32+
}, myFunctionImpl)
33+
}
34+
35+
func myFunctionImpl(bctx topdown.BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
36+
// Extract arguments
37+
input, ok := operands[0].Value.(ast.String)
38+
if !ok {
39+
return fmt.Errorf("input must be a string")
40+
}
41+
42+
// Implement logic
43+
result := processInput(string(input))
44+
45+
// Return result
46+
return iter(ast.StringTerm(result))
47+
}
48+
49+
// Autoregisters on package load
50+
func init() {
51+
if err := RegisterMyBuiltins(); err != nil {
52+
panic(fmt.Sprintf("failed to register built-ins: %v", err))
53+
}
54+
}
55+
```
56+
57+
2. **Use in Policies** (`*.rego`):
58+
```rego
59+
package example
60+
import rego.v1
61+
62+
result := {
63+
"violations": violations,
64+
"skipped": false
65+
}
66+
67+
violations contains msg if {
68+
output := chainloop.my_function(input.value)
69+
output != "expected"
70+
msg := "Function returned unexpected value"
71+
}
72+
```
73+
74+
**Guidelines**:
75+
- Use `chainloop.*` namespace for all custom built-ins
76+
- Functions that call third party services should be marked as non-restrictive by adding the `NonRestrictiveBuiltin` category to the builtin definition
77+
- Always implement proper error handling and return meaningful error messages
78+
- Use context from `BuiltinContext` for timeout/cancellation support
79+
- Document function signatures and behavior in the `Description` field and parameter definitions

CLAUDE.md

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -246,91 +246,6 @@ Workflow Contracts define the structure and requirements for CI/CD attestations.
246246
- **Authentication**: JWT tokens generated by Control Plane, validated by CAS
247247
- **Streaming**: Uses gRPC bytestream protocol for efficient file transfers
248248

249-
### Policy Engine Extension
250-
251-
The OPA/Rego policy engine supports custom built-in functions written in Go.
252-
253-
**Architecture** (`pkg/policies/engine/rego/builtins/`):
254-
- **Registry**: Manages custom built-in function registration
255-
- **Security Levels**: Functions tagged as `SecurityLevelRestrictive` (production-safe) or `SecurityLevelPermissive` (development-only)
256-
- **Operating Modes**: Restrictive mode (server-side) only allows restrictive functions; Permissive mode (CLI local dev) allows all functions
257-
258-
**Adding Custom Built-ins**:
259-
260-
1. **Create Built-in Implementation** (e.g., `pkg/policies/engine/rego/builtins/myfeature.go`):
261-
```go
262-
package builtins
263-
264-
import (
265-
"github.com/open-policy-agent/opa/ast"
266-
"github.com/open-policy-agent/opa/topdown"
267-
"github.com/open-policy-agent/opa/types"
268-
)
269-
270-
const myFuncName = "chainloop.my_function"
271-
272-
func RegisterMyBuiltins() error {
273-
return Register(&BuiltinDef{
274-
Name: myFuncName,
275-
Decl: &ast.Builtin{
276-
Name: myFuncName,
277-
Decl: types.NewFunction(
278-
types.Args(types.Named("input", types.S)),
279-
types.Named("result", types.S),
280-
),
281-
},
282-
Impl: myFunctionImpl,
283-
SecurityLevel: SecurityLevelRestrictive, // or SecurityLevelPermissive
284-
Description: "Description of what this function does",
285-
})
286-
}
287-
288-
func myFunctionImpl(bctx topdown.BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
289-
// Extract arguments
290-
input, ok := operands[0].Value.(ast.String)
291-
if !ok {
292-
return fmt.Errorf("input must be a string")
293-
}
294-
295-
// Implement logic
296-
result := processInput(string(input))
297-
298-
// Return result
299-
return iter(ast.StringTerm(result))
300-
}
301-
302-
func init() {
303-
if err := RegisterMyBuiltins(); err != nil {
304-
panic(fmt.Sprintf("failed to register built-ins: %v", err))
305-
}
306-
}
307-
```
308-
309-
2. **Use in Policies** (`*.rego`):
310-
```rego
311-
package example
312-
import rego.v1
313-
314-
result := {
315-
"violations": violations,
316-
"skipped": false
317-
}
318-
319-
violations contains msg if {
320-
output := chainloop.my_function(input.value)
321-
output != "expected"
322-
msg := "Function returned unexpected value"
323-
}
324-
```
325-
326-
**Guidelines**:
327-
- Use `chainloop.*` namespace for all custom built-ins
328-
- Restrictive functions must be read-only, deterministic, and not make external calls
329-
- Permissive functions can call external services
330-
- Always implement proper error handling and return meaningful error messages
331-
- Use context from `BuiltinContext` for timeout/cancellation support
332-
- Document function signatures and behavior in the `Description` field
333-
334249
## Commit Guidelines
335250

336251
All commits must meet these criteria:

pkg/policies/engine/rego/builtins/registry.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ import (
1919
"github.com/open-policy-agent/opa/v1/topdown"
2020
)
2121

22-
// SecurityLevel defines when a built-in function is allowed to execute
23-
type SecurityLevel int
24-
2522
const (
2623
// NonRestrictiveBuiltin is used in builtin definition categories to mark a builtin as non-suitable for Chainloop's restrictive mode
2724
NonRestrictiveBuiltin = "non-restrictive"

0 commit comments

Comments
 (0)