alert_pending_transfers
Aggregate-vs-aggregate comparison (parenthesized left, bare right): permit an
Alert when there are more Transfer requests than responses in the last
hour — i.e. some transfers are still pending.
The left count for (t: Timepoint). where (…) aggregate is parenthesized so its
greedy where body does not swallow the < operator; the right aggregate is
rightmost so it needs no parens.
World: drupe. Schema lifted from the temporal_only corpus case
ea_0014_agg_vs_agg (has the Transfer and Alert actions). Default event
schema; no trace.
Referenced by guide/04-temporal-expressions.
Policy
// An aggregate on BOTH sides of a comparison. The LEFT aggregate is
// parenthesized so its greedy `where` body does not swallow the `<` operator;
// the RIGHT is rightmost so it needs no parens. Permit an Alert if there are
// more Transfer requests than responses in the last hour (some pending).
@id("alert_pending_transfers")
permit (
principal,
action == Drupe::Action::"Alert",
resource
)
when temporal {
(count for (t: Timepoint). where (
formerly within 1h (Drupe::Action::"Transfer"::response{ requestId: _ } && tp(t))
))
< count for (t: Timepoint). where (
formerly within 1h (Drupe::Action::"Transfer"::request{ requestId: _ } && tp(t))
)
};
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
}
};
}