alert_same_principal_login_transfer
An entity-typed exists binder that correlates on the request principal
via the reserved callerPrincipal field. The policy permits an Alert only
if the same principal both logged in (Login) and made a transfer
(Transfer) within the last hour — the join on the bound pr: Drupe::OAuthUser variable is the whole point.
The guide illustrates the pattern with Login + Deny, but no shipped schema
declares a Deny action, so this example is adapted to Login + Transfer
(both present in the lifted ea_0012_exists_correlation schema). The shape of
the correlation — callerPrincipal: pr on both sides — is identical.
Schema lifted from the temporal_only corpus case
ea_0012_exists_correlation (declares Login, Transfer, Alert, and the
OAuthUser entity). Uses the default event schema.
Referenced by guide/04-temporal-expressions.
Policy
// An entity-typed `exists` binder correlates on the request principal via the
// reserved callerPrincipal field. Permit an Alert if the SAME principal both
// logged in and transferred within the last hour. (The guide illustrates this
// with Login+Deny; adapted here to Login+Transfer since no shipped schema
// declares a Deny action.)
@id("alert_same_principal_login_and_transfer")
permit (
principal,
action == Drupe::Action::"Alert",
resource
)
when temporal {
exists (pr: Drupe::OAuthUser). (
formerly within 1h Drupe::Action::"Login"::request{ callerPrincipal: pr }
&& formerly within 1h Drupe::Action::"Transfer"::request{ callerPrincipal: pr }
)
};
Schema
namespace Drupe {
type AlertInput = {
level: Long,
server: String
};
type AlertOutput = { };
type ContentFilterFinding = {
severityScore: decimal
};
type HeartbeatInput = {
server: String
};
type HeartbeatOutput = { };
type LoginInput = {
server: String,
user: String
};
type LoginOutput = { };
type PromptAttackFinding = {
severityScore: decimal
};
type SensitiveInfoFinding = {
confidenceScore: decimal
};
type SystemContext = {
now: datetime
};
type TransferInput = {
amount: Long,
user: String
};
type TransferOutput = { };
entity Gateway;
entity IamEntity = {
id: String
};
entity OAuthUser = {
id: String
} tags String;
entity UnauthenticatedUser;
action "Alert" in [Action::"CallTool"] appliesTo {
principal: [IamEntity, OAuthUser, UnauthenticatedUser],
resource: [Gateway],
context: {
input: AlertInput,
output?: AlertOutput,
system: SystemContext
}
};
action "CallTool" in [Action::"Mcp"] appliesTo {
principal: [OAuthUser, IamEntity, UnauthenticatedUser],
resource: [Gateway],
context: {
system: SystemContext
}
};
action "Heartbeat" in [Action::"CallTool"] appliesTo {
principal: [IamEntity, OAuthUser, UnauthenticatedUser],
resource: [Gateway],
context: {
input: HeartbeatInput,
output?: HeartbeatOutput,
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 "Login" in [Action::"CallTool"] appliesTo {
principal: [IamEntity, OAuthUser, UnauthenticatedUser],
resource: [Gateway],
context: {
input: LoginInput,
output?: LoginOutput,
system: SystemContext
}
};
action "Mcp" appliesTo {
principal: [OAuthUser, IamEntity, UnauthenticatedUser],
resource: [Gateway],
context: {
system: SystemContext
}
};
action "Transfer" in [Action::"CallTool"] appliesTo {
principal: [IamEntity, OAuthUser, UnauthenticatedUser],
resource: [Gateway],
context: {
input: TransferInput,
output?: TransferOutput,
system: SystemContext
}
};
action "UnknownTool" in [Action::"CallTool"] appliesTo {
principal: [OAuthUser, IamEntity, UnauthenticatedUser],
resource: [Gateway],
context: {
system: SystemContext
}
};
}