Jiffy

agentgateway CEL policy pack

Package: @jiffylabs/agentgateway-policy-pack · Version: 0.1.0 · License: Apache-2.0

The agentgateway policy pack ships eight reference CEL (Common Expression Language) bundles that map Jiffy trust decisions — tier, ail_level, jts_score, framework_codes, parent_invalidated — into agentgateway's native policy engine. Paste a bundle into your agentgateway control plane and it will permit, warn, or block MCP tool calls statically at the gateway, while still delegating dynamic verdicts to the Sprint 52 Jiffy webhook (https://trust.jiffylabs.app/v1/agentgateway/guardrail).

  • Static CEL pre-filter — declarative rules your SREs can read, diff, and promote through kubectl apply.
  • Webhook fallback — live tier and AIL evaluation via the Jiffy trust endpoint, same shape as @jiffylabs/agentgateway-adapter.
  • Eight seed bundles covering malicious-block, SOC 2 finance restriction, tier-1-only, agentic approval, framework-code coverage, and blast-radius parent invalidation.

Bundle catalog

SlugDefault decisionWebhook requiredFramework codesCEL
malicious-blockpermityesOWASP-Agentic-2026, MITRE-ATLASdecision.tier == "CRITICAL" ? "block" : "permit"
critical-onlypermityesOWASP-Agentic-2026, NIST-CSF-2.0(decision.tier in ["RISKY", "CRITICAL"]) && decision.ail_level >= 4 ? "block" : "permit"
finance-restrictedpermityesSOC2-CC6.1, OWASP-Agentic-2026, NIST-CSF-2.0startsWith(request.mcp_server, "prod-") ? (decision.tier == "CAUTION" ? "warn" : (decision.tier in ["RISKY", "CRITICAL"] ? "block" : "permit")) : "permit"
dev-permissivewarnyes(none — dev only)decision.tier == "CRITICAL" ? "block" : "warn"
agentic-only-with-approvalpermityesOWASP-Agentic-2026, NIST-CSF-2.0decision.ail_level >= 4 ? "warn" : "permit"
tier1-onlyblockyesSOC2-CC6.1, NIST-CSF-2.0decision.tier == "TRUSTED" ? "permit" : "block"
framework-codes-soc2permityesSOC2-CC6.1, OWASP-Agentic-2026, NIST-CSF-2.0contains(decision.framework_codes, "OWASP-Agentic-2026") && contains(decision.framework_codes, "NIST-CSF-2.0") ? "permit" : "block"
blast-radius-guardpermityesOWASP-Agentic-2026, MITRE-ATLAShas(decision.parent_invalidated) && decision.parent_invalidated == true ? "block" : "permit"

All eight bundles invoke the Jiffy guardrail webhook for live tier and AIL resolution. requires_webhook: false is reserved for future bundles that are fully self-contained in CEL.


Bundle details

1. malicious-block — Block malicious tier

Blocks any MCP tool call whose Jiffy trust tier evaluates to CRITICAL. The customer-facing framing is "malicious"; the Jiffy webhook wire vocabulary uses CRITICAL as the highest-risk tier.

Default MCP route binding: mcp-malicious-blockmcp.github.com

decision.tier == "CRITICAL" ? "block" : "permit"

Verdict table

decision.tierVerdict
CRITICALblock
RISKYpermit
CAUTIONpermit
TRUSTEDpermit
PENDINGpermit

2. critical-only — Block RISKY/CRITICAL at AIL 4+

Blocks tool calls that combine a high trust risk (RISKY or CRITICAL) with a high agentic-impact level (>= 4). Everything else permits.

Default MCP route binding: mcp-critical-onlymcp.linear.app

(decision.tier in ["RISKY", "CRITICAL"]) && decision.ail_level >= 4 ? "block" : "permit"

Verdict table

decision.tierdecision.ail_levelVerdict
CRITICAL5block
CRITICAL3permit
RISKY4block
CAUTION5permit
TRUSTEDanypermit

3. finance-restricted — SOC 2 finance restriction

Warn on CAUTION tier, block on RISKY or CRITICAL, but only for production finance MCP servers (mcp_server starts with prod-). Non-prod traffic passes through unaffected.

Default MCP route binding: mcp-finance-restrictedprod-payments-mcp

startsWith(request.mcp_server, "prod-") ? (decision.tier == "CAUTION" ? "warn" : (decision.tier in ["RISKY", "CRITICAL"] ? "block" : "permit")) : "permit"

Verdict table

request.mcp_serverdecision.tierVerdict
prod-payments-mcpCRITICALblock
prod-payments-mcpCAUTIONwarn
prod-payments-mcpTRUSTEDpermit
dev-sandbox-mcpCRITICALpermit

4. dev-permissive — Dev sandbox, warn-only

Permits every call with a warn annotation except CRITICAL tier. Intended for local dev / sandbox use; do not ship to production. Empty framework_codes — this is not a compliance posture.

Default MCP route binding: mcp-dev-permissivedev-sandbox-mcp

decision.tier == "CRITICAL" ? "block" : "warn"

Verdict table

decision.tierVerdict
CRITICALblock
any otherwarn

5. agentic-only-with-approval — High agentic impact → require approval

For calls with agentic-impact level >= 4, emit a warn verdict with reason manual_approval_required so the agentgateway operator can route the call into its approval system. Low-impact calls pass through.

Default MCP route binding: mcp-agentic-approvalmcp.notion.com

decision.ail_level >= 4 ? "warn" : "permit"

Verdict table

decision.ail_levelVerdict
5warn (reason: manual_approval_required)
4warn (reason: manual_approval_required)
3permit
1permit

6. tier1-only — TRUSTED tier only

Strictest posture in the seed pack: permit only TRUSTED-tier traffic; everything else (CAUTION, RISKY, CRITICAL, PENDING) is blocked. Use for air-gapped or tier-1 data classifications.

Default MCP route binding: mcp-tier1-onlymcp.github.com

decision.tier == "TRUSTED" ? "permit" : "block"

Verdict table

decision.tierVerdict
TRUSTEDpermit
any otherblock

7. framework-codes-soc2 — SOC 2 framework-code coverage

Asserts framework coverage rather than artifact risk: permit only when the decision carries both OWASP-Agentic-2026 and NIST-CSF-2.0 framework codes. Used for SOC 2 CC6.1 evidence trails.

Default MCP route binding: mcp-framework-codes-soc2mcp.linear.app

contains(decision.framework_codes, "OWASP-Agentic-2026") && contains(decision.framework_codes, "NIST-CSF-2.0") ? "permit" : "block"

Verdict table

decision.framework_codesVerdict
contains both OWASP-Agentic-2026 and NIST-CSF-2.0permit
missing eitherblock

8. blast-radius-guard — Parent-artifact invalidation

Blocks tool calls whose parent artifact has been invalidated by a Sprint-22-linked disclosure event. Reads the webhook decision flag parent_invalidated — absent or false means permit.

Default MCP route binding: mcp-blast-radius-guardmcp.notion.com

has(decision.parent_invalidated) && decision.parent_invalidated == true ? "block" : "permit"

Verdict table

decision.parent_invalidatedVerdict
trueblock
falsepermit
missingpermit

CEL subset reference

Sprint 53 ships a frozen in-tree CEL validator and evaluator (packages/agentgateway-policy-pack/src/cel/). The supported subset is deliberately small — any bundle needing more is rewritten, not extended.

Literals

  • Integer: 0, 4, 5
  • String: "CRITICAL", "prod-payments-mcp"
  • Boolean: true, false

Operators

CategoryOperators
Equality==, !=
Ordering<, <=, >, >= (integers only)
Membershipin (left scalar, right list literal: tier in ["RISKY", "CRITICAL"])
Logical&&, `, !`
Ternarycond ? a : b

Field paths

Dotted paths only; single bracketed string-key access permitted for request.headers. Deeper nesting is not supported.

  • decision.tierTRUSTED | CAUTION | RISKY | CRITICAL | PENDING
  • decision.ail_level — integer 1–5
  • decision.jts_score — integer 0–100
  • decision.parent_invalidated — boolean
  • decision.framework_codes — string list
  • request.tool — tool identifier string
  • request.agent — agent identifier string
  • request.mcp_server — MCP server hostname
  • request.headers["X-Agent-Id"] — single header lookup

Built-in functions

Three only; no user-definable functions.

  • startsWith(s, prefix) → boolean
  • contains(list_or_string, needle) → boolean
  • has(decision.field) → boolean (true when the field is present and non-null)

Anything outside this subset is a CEL_VALIDATION_ERROR. Validator and evaluator share the same parser, so a policy that validates is guaranteed to evaluate (or throw a typed runtime error if the context is missing a referenced field).


Webhook URL customization

All eight bundles invoke the Jiffy trust webhook for live tier and AIL decisions. The default URL is https://trust.jiffylabs.app/v1/agentgateway/guardrail. Override it at emit time:

jiffy export-agentgateway-policy malicious-block \
  --webhook-url=https://hook.internal.example/jiffy-guardrail

The emitted YAML's Webhook resource embeds the URL verbatim; no other substitution is performed. See the Sprint 52 webhook docs for the request/response schema, authentication, and idempotency guarantees expected by agentgateway operators.


How to deploy

  1. Install the CLI: pnpm add -g @jiffylabs/jiffy-cli (or run from source via pnpm -F @jiffylabs/jiffy-cli start).
  2. Emit the bundle YAML: jiffy export-agentgateway-policy <slug>.
  3. Apply to your agentgateway control plane: kubectl apply -f -.

Example: jiffy export-agentgateway-policy malicious-block

# Generated by @jiffylabs/jiffy-cli (agentgateway-policy-pack 0.1.0)
# Bundle: malicious-block @ 1.0.0
# CEL SHA-256 pin: 724d5fe3f592e8b64b207dd8fff072d5a771fa55b3cfdca974e0d6481b01da4d
# Frameworks: OWASP-Agentic-2026, MITRE-ATLAS
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: mcp-malicious-block-gateway
  annotations:
    jiffy.io/bundle: "malicious-block"
spec:
  gatewayClassName: agentgateway
  listeners:
    - name: mcp
      port: 443
      protocol: HTTPS
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: mcp-malicious-block
spec:
  parentRefs:
    - name: mcp-malicious-block-gateway
  rules:
    - backendRefs:
      - name: mcp.github.com
        port: 443
---
apiVersion: agentgateway.dev/v1alpha1
kind: Policy
metadata:
  name: malicious-block
  labels:
    jiffy.io/bundle: "malicious-block"
    jiffy.io/pack-version: "0.1.0"
spec:
  targetRefs:
    - kind: HTTPRoute
      name: mcp-malicious-block
  defaultDecision: permit
  cel: |
    decision.tier == "CRITICAL" ? "block" : "permit"
---
apiVersion: agentgateway.dev/v1alpha1
kind: Webhook
metadata:
  name: malicious-block-jiffy-guardrail
spec:
  url: https://trust.jiffylabs.app/v1/agentgateway/guardrail
  forwardHeaderMatches:
    - X-Agent-Id
  policyRef:
    name: malicious-block

Exit codes

The CLI aligns with the existing jiffy export-mdm exit-code map:

CodeMeaning
0success
1generic failure (reserved)
2unknown bundle slug
3malformed CLI input (missing slug, bad flag value, CEL validation error)

Hardening bundle integration

Sprint 54 (F70) — composes the CEL policy above with a hardening bundle's Gateway + HTTPRoute metadata into a single kubectl apply-ready YAML.

Each Jiffy hardening template (see /templates) can optionally carry an agentgateway_bundle manifest. When set, the template pairs a CEL slug from this pack with a Gateway name + optional route overrides + optional webhook URL override. The CLI command jiffy export-agentgateway-bundle <bundle-slug> emits the combined deployment YAML.

Seed bundle pairings

The four seed hardening bundles ship with these default CEL pairings (migration 049 + web/src/lib/hardening-templates/seed.ts):

Hardening bundleCEL policy slugGateway nameStatus
soc2-claude-codeframework-codes-soc2soc2-claude-code-gatewaydeployable
cursor-enterprise-restrictedfinance-restrictedcursor-enterprise-gatewaydeployable
amazonq-finance-regulatedfinance-restrictedamazonq-finance-gatewaydeployable
claude-desktop-locked-downtier1-onlyclaude-desktop-locked-gatewaydeployable

The 2-of-4 deployable gate (per the Sprint 54 contract): soc2-claude-code and cursor-enterprise-restricted are the formal deployable gate; the other two are expected to pass CRD validation but are not gate-blocking.

CRD schema pin

The emitter validates emitted documents against vendored upstream agentgateway CRD schemas at packages/jiffy-cli/src/vendored/agentgateway-crd-schemas.json. The file's pinned_sha field pins the upstream commit from https://github.com/agentgateway/agentgateway we validated against. Bumping the pin is a deliberate, separate sprint step.

Web surface

  • Customer-facing: /templates/[slug] renders a collapsible "agentgateway deployment" section below the file manifest when agentgateway_bundle is set. A Download YAML button hits /api/v1/templates/[id]/agentgateway.yaml (Content-Type text/yaml; charset=utf-8).
  • Admin-facing: /admin/templates per-row expandable details show file_manifest + agentgateway_bundle JSON in read-only panels.

Related

  • Webhook schema../../packages/agentgateway-adapter/README.md (Sprint 52; request/response shape, header forwarding, idempotency).
  • Policy pack source../../packages/agentgateway-policy-pack/README.md.
  • CLI source (single policy)../../packages/jiffy-cli/src/commands/export-agentgateway-policy.ts.
  • CLI source (bundle)../../packages/jiffy-cli/src/commands/export-agentgateway-bundle.ts.
  • Shared emitter../../packages/jiffy-cli/src/lib/agentgateway-yaml.ts.
  • Upstream agentgateway docs — https://agentgateway.dev