Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

cedar_semver_gt

The RFC 0061 semver worked example for Cedar macros: a record-building macro (semver, which constructs a { major, minor, patch } record) passed as an argument to a comparator macro (semverGT). Nesting one macro call as an argument to another is allowed — the compiler expands call arguments first, then splices the result into the outer macro’s body.

Both macros are declared inline in policy.dw. The rule uses constant arguments and a bare action scope, so it validates against the Drupe schema (copied from write_after_read) with no event history.

Referenced by guide/06-macros.md.

Policy

// RFC 0061 worked example: `semver` builds a { major, minor, patch }
// record that `semverGT` compares. Nesting one macro call as an argument
// to another is allowed (call arguments are expanded first).
def cedar semver(?major, ?minor, ?patch) {
    { major: ?major, minor: ?minor, patch: ?patch }
};
def cedar semverGT(?a, ?b) {
    if ?a.major == ?b.major
    then (if ?a.minor == ?b.minor then ?a.patch > ?b.patch else ?a.minor > ?b.minor)
    else ?a.major > ?b.major
};

@id("semver_gt_constant")
permit (principal, action, resource)
when { semverGT(semver(2, 1, 1), semver(2, 1, 0)) };

Schema

namespace Drupe {
  type ApproveSaleInput = {
    shares: Long,
    stock: String
  };

  type ApproveSaleOutput = {
    approved: Bool
  };

  type ContentFilterFinding = {
    severityScore: decimal
  };

  type GetStockInfoInput = {
    stock: String
  };

  type GetStockInfoOutput = {
    info: String
  };

  type PromptAttackFinding = {
    severityScore: decimal
  };

  type SellSharesInput = {
    shares: Long,
    stock: String
  };

  type SellSharesOutput = {
    proceeds: decimal
  };

  type SensitiveInfoFinding = {
    confidenceScore: decimal
  };

  type SystemContext = {
    now: datetime
  };

  entity Gateway;

  entity IamEntity = {
    id: String
  };

  entity OAuthUser = {
    id: String
  } tags String;

  entity UnauthenticatedUser;

  action "ApproveSale" in [Action::"CallTool"] appliesTo {
    principal: [IamEntity, OAuthUser, UnauthenticatedUser],
    resource: [Gateway],
    context: {
      input: ApproveSaleInput,
      output?: ApproveSaleOutput,
      system: SystemContext
    }
  };

  action "CallTool" in [Action::"Mcp"] appliesTo {
    principal: [OAuthUser, IamEntity, UnauthenticatedUser],
    resource: [Gateway],
    context: {
      system: SystemContext
    }
  };

  action "GetStockInfo" in [Action::"CallTool"] appliesTo {
    principal: [IamEntity, OAuthUser, UnauthenticatedUser],
    resource: [Gateway],
    context: {
      input: GetStockInfoInput,
      output?: GetStockInfoOutput,
      system: SystemContext
    }
  };

  action "Http" appliesTo {
    principal: [OAuthUser, IamEntity, UnauthenticatedUser],
    resource: [Gateway],
    context: {
      system: SystemContext
    }
  };

  action "InvokeAgent" in [Action::"Http"] appliesTo {
    principal: [OAuthUser, IamEntity, UnauthenticatedUser],
    resource: [Gateway],
    context: {
      input?: {      },
      system: SystemContext
    }
  };

  action "InvokeLLM" in [Action::"Http"] appliesTo {
    principal: [OAuthUser, IamEntity, UnauthenticatedUser],
    resource: [Gateway],
    context: {
      input?: {      },
      system: SystemContext
    }
  };

  action "Mcp" appliesTo {
    principal: [OAuthUser, IamEntity, UnauthenticatedUser],
    resource: [Gateway],
    context: {
      system: SystemContext
    }
  };

  action "SellShares" in [Action::"CallTool"] appliesTo {
    principal: [IamEntity, OAuthUser, UnauthenticatedUser],
    resource: [Gateway],
    context: {
      input: SellSharesInput,
      output?: SellSharesOutput,
      system: SystemContext
    }
  };

  action "UnknownTool" in [Action::"CallTool"] appliesTo {
    principal: [OAuthUser, IamEntity, UnauthenticatedUser],
    resource: [Gateway],
    context: {
      system: SystemContext
    }
  };
}