Deploys openpolicyagent/opa:0.68.0 as a single-replica ClusterIP
service in the scobleclaw namespace, with a ConfigMap-mounted
policy bundle under /policies.
Policies (package scobleclaw):
_lib.rego shared deny rules (external email, forgejo
write outside marcus/engineering, payment
kamelets) + helpers (is_external_email,
is_payment_kamelet, is_forgejo_write_outside_allowed)
main-agent.rego 10-kamelet allowlist for main-agent
demo-concierge.rego read-only 4-kamelet allowlist
demo-watchdog.rego 4-kamelet allowlist (ob1 + discord)
L0 contract:
POST /v1/data/scobleclaw/allow -> {allow: bool}
POST /v1/data/scobleclaw/needs_l1 -> {needs_l1: bool}
POST /v1/data/scobleclaw/deny -> [reason, ...]
Verified end-to-end against the running OPA pod:
allow=true for main-agent + kamelet:source/forgejo-search
deny=[reason] for external email, forgejo write to stranger/not-mine,
payment kamelet (stripe-charge), demo-concierge forgejo-create
needs_l1=true for unknown kamelet (e.g. some-new-kamelet) on main-agent
needs_l1=false for payment kamelet (L1 cannot override L0 deny)
Out of scope (separate tickets): judge-integration Camel-K binding,
llm-classifier-integration (L1), discord-escalation-integration (L2),
audit-sink OPA log tailing.
76 lines
1.9 KiB
YAML
76 lines
1.9 KiB
YAML
---
|
|
# Single-replica OPA deployment. Fail-closed: if the pod dies, agents fall
|
|
# back to deny-by-default (the L1/L2 callers treat an OPA timeout as deny).
|
|
#
|
|
# Resource footprint is intentionally small: 64Mi mem, 100m CPU. Rego
|
|
# evaluation is <1ms per call so we don't need a beefy pod.
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: opa
|
|
namespace: scobleclaw
|
|
labels:
|
|
app: opa
|
|
component: l0-judge
|
|
spec:
|
|
replicas: 1
|
|
strategy:
|
|
# Recreate avoids split-brain while the ConfigMap volume is being
|
|
# remounted on a content change.
|
|
type: Recreate
|
|
selector:
|
|
matchLabels:
|
|
app: opa
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: opa
|
|
component: l0-judge
|
|
spec:
|
|
serviceAccountName: opa
|
|
containers:
|
|
- name: opa
|
|
image: openpolicyagent/opa:0.68.0
|
|
imagePullPolicy: IfNotPresent
|
|
args:
|
|
- "run"
|
|
- "--server"
|
|
- "--addr=http://0.0.0.0:8181"
|
|
- "--log-level=info"
|
|
- "--log-format=json"
|
|
- "/policies"
|
|
ports:
|
|
- name: http
|
|
containerPort: 8181
|
|
protocol: TCP
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: http
|
|
initialDelaySeconds: 2
|
|
periodSeconds: 5
|
|
timeoutSeconds: 2
|
|
failureThreshold: 3
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: http
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 15
|
|
timeoutSeconds: 2
|
|
failureThreshold: 3
|
|
resources:
|
|
requests:
|
|
cpu: 50m
|
|
memory: 64Mi
|
|
limits:
|
|
cpu: 500m
|
|
memory: 256Mi
|
|
volumeMounts:
|
|
- name: policies
|
|
mountPath: /policies
|
|
readOnly: true
|
|
volumes:
|
|
- name: policies
|
|
configMap:
|
|
name: opa-policies
|