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

call_cedar_macro_as_argument

A Cedar macro call passed as an argument to another macro call: semverGT(semver(2, 1, 1), semver(2, 1, 0)). The inner semver(...) calls expand into record literals first, then splice into the outer semverGT(...) call, which expands into the nested if/comparison. The result is a constant-true guard (2.1.1 > 2.1.0), so the permit fires for every Drupe::Action::"GetStockInfo" request.

The two macros (semver, semverGT) are lifted verbatim from macros corpus 0036_semver_rfc0061 (Cedar RFC-0061, translated to Dogwood) and live in macros.dw, passed via --macros.

Validate (run from this directory):

dogwood validate policy.dw --policy-schema schema.cedarschema --macros macros.dw

Referenced by guide/09-calling-macros.md.

Policy

// A macro call passed as an ARGUMENT to another macro call: the inner
// semver(...) records are expanded first, then spliced into semverGT.
// (RFC-0061 semantic-versioning macros, translated to Dogwood.)
@id("gate_on_semver_compare")
permit (principal, action == Drupe::Action::"GetStockInfo", 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
    }
  };
}

Macros

// RFC-0061 semantic-versioning macros (lifted verbatim from macros corpus
// 0036_semver_rfc0061/policy_1.dw): a record-building macro `semver` and a
// comparing macro `semverGT`. `semver(...)` may be passed as an argument to
// `semverGT(...)` — the inner calls expand first, then splice in.
def cedar semver(?major, ?minor, ?patch) {
    { major: ?major, minor: ?minor, patch: ?patch }
};

def cedar semverGT(?lhs, ?rhs) {
    if ?lhs.major == ?rhs.major then
        if ?lhs.minor == ?rhs.minor then
            ?lhs.patch > ?rhs.patch
        else
            ?lhs.minor > ?rhs.minor
    else
        ?lhs.major > ?rhs.major
};