Author a Policy

Build deterministic executable authorization logic and test allow, deny, and constraint behavior before attachment.

Before you begin

Write down the one authorization-target kind and selector the Policy should govern, the normalized identity evidence it may use, and the constraints it should add. A target may be a managed Resource or a platform address such as a session, binding, or deployment. Executable Policy code is deterministic: it has no network, secret, storage, clock, or random authority. Use request input only.

Steps

  1. Create an ESM package and install the SDK with npm install @constal/sdk.
  2. Export a Policy definition:
src/index.ts
import { policy, type PolicyOutcome } from "@constal/sdk";

export default policy({
  id: "ticket-read-boundary",
  version: "1.0.0",
  evaluate(input): PolicyOutcome {
    const isRead = input.context["resource.operation"] === "ticket.read";
    return isRead
      ? { kind: "constrain", constraints: [
          { kind: "context", equals: { "request.region": "us" } },
        ] }
      : { kind: "deny", code: "read-only", reason: "read only" };
  },
});
  1. Add constal.policy.json with the same id and version, its entrypoint, namespace, and one required target selector:
constal.policy.json
{
  "schemaVersion": 3,
  "kind": "policy",
  "id": "ticket-read-boundary",
  "namespace": "default",
  "version": "1.0.0",
  "entry": "src/index.ts",
  "target": {
    "resourceKind": "service",
    "selector": {
      "matchLabels": { "access": "support" }
    }
  },
  "policies": []
}

The selector uses the same normalized matchLabels and matchExpressions semantics as Channel-to-Agent selection. It cannot cross the authenticated environment, tenant, or namespace boundary. Use the protected constal.ai/crn label when exactly one Resource should match.

  1. Unit test allowed, denied, malformed, and boundary inputs with evaluatePolicyDefinition(). The execution environment—not Policy code—validates the outcome and creates protocol hashes.
  2. Upload the archive through the common deployment workflow.

Verify

Call POST /v1/namespaces/:namespace/policies/:id/evaluate with a representative action, deployed Resource, and optional context. This endpoint is explicitly a non-enforcing simulation: confirm simulation: true, enforcing: false, the exact target hash, decision, and Policy hash. Admission resolves and evaluates its own accepted snapshot; it never reuses a simulation result.

Next steps

Continue with Operate Policies to inspect its selected Resources. See Govern Resource usage for controls and limits, Policies and analytics for the SDK boundary, and Deploy an Agent for the shared package upload model.