temporal_once_read_recent
A condition-flavoured temporal macro. def temporal once(?w, ?s) { formerly within ?w ?s } wraps a window ?w and a whole condition ?s in formerly within, so it is callable wherever a temporal condition is expected. The
policy permits when the same user recently (within 1h) issued a Read for the
same document, pinning both fields via input.user: context.input.user and
input.document: context.input.document.
The macro is defined inline in policy.dw (no separate macros.dw), and
the schema (schema.cedarschema, which carries a Read action) is copied from
tests/passing/macros/corpus/0020_condition_macro_bare.
The trace shows both outcomes:
@0— aliceReadsdoc1; theonce(...)condition matches at the current timepoint → allow.@100— aliceWritesdoc1, 100s after her read → allow (a matching read for the same user + document is within the window).@200— bobWritesdoc2with no prior read → deny.
Referenced by guide/06-macros.md.
Policy
// A condition-flavoured temporal macro. `once(?w, ?s)` wraps a window and a
// whole condition in `formerly within`. Callable wherever a temporal
// condition is expected.
def temporal once(?w, ?s) { formerly within ?w ?s };
@id("read_recently_via_once")
permit (principal, action in [Drupe::Action::"Read", Drupe::Action::"Write"], resource)
when temporal {
once(1h, Drupe::Action::"Read"::request{
input.user: context.input.user,
input.document: context.input.document
})
};
Schema
namespace Drupe {
type ApproveInput = {
approver: String,
request_id: String
};
type ApproveOutput = {
result: Bool
};
type ContentFilterFinding = {
severityScore: decimal
};
type LoginInput = {
server: String,
user: String
};
type LoginOutput = {
result: Bool
};
type LogoutInput = {
server: String,
user: String
};
type LogoutOutput = {
result: Bool
};
type PromptAttackFinding = {
severityScore: decimal
};
type ReadInput = {
document: String,
user: String
};
type ReadOutput = {
result: Bool
};
type SensitiveInfoFinding = {
confidenceScore: decimal
};
type SubmitInput = {
request_id: String,
user: String
};
type SubmitOutput = {
result: Bool
};
type SystemContext = {
now: datetime
};
type WriteInput = {
document: String,
user: String
};
type WriteOutput = {
result: Bool
};
entity Gateway;
entity IamEntity = {
id: String
};
entity OAuthUser = {
id: String
} tags String;
entity UnauthenticatedUser;
action "Approve" in [Action::"CallTool"] appliesTo {
principal: [IamEntity, OAuthUser, UnauthenticatedUser],
resource: [Gateway],
context: {
input: ApproveInput,
output?: ApproveOutput,
system: SystemContext
}
};
action "CallTool" in [Action::"Mcp"] appliesTo {
principal: [OAuthUser, IamEntity, UnauthenticatedUser],
resource: [Gateway],
context: {
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 "Logout" in [Action::"CallTool"] appliesTo {
principal: [IamEntity, OAuthUser, UnauthenticatedUser],
resource: [Gateway],
context: {
input: LogoutInput,
output?: LogoutOutput,
system: SystemContext
}
};
action "Mcp" appliesTo {
principal: [OAuthUser, IamEntity, UnauthenticatedUser],
resource: [Gateway],
context: {
system: SystemContext
}
};
action "Read" in [Action::"CallTool"] appliesTo {
principal: [IamEntity, OAuthUser, UnauthenticatedUser],
resource: [Gateway],
context: {
input: ReadInput,
output?: ReadOutput,
system: SystemContext
}
};
action "Submit" in [Action::"CallTool"] appliesTo {
principal: [IamEntity, OAuthUser, UnauthenticatedUser],
resource: [Gateway],
context: {
input: SubmitInput,
output?: SubmitOutput,
system: SystemContext
}
};
action "UnknownTool" in [Action::"CallTool"] appliesTo {
principal: [OAuthUser, IamEntity, UnauthenticatedUser],
resource: [Gateway],
context: {
system: SystemContext
}
};
action "Write" in [Action::"CallTool"] appliesTo {
principal: [IamEntity, OAuthUser, UnauthenticatedUser],
resource: [Gateway],
context: {
input: WriteInput,
output?: WriteOutput,
system: SystemContext
}
};
}
Trace
@0 scope(principal: Drupe::OAuthUser::"alice", resource: Drupe::Gateway::"gw1") request_context(input: { document: "doc1", user: "alice" }) Drupe::Action::"Read"::request(input: { document: "doc1", user: "alice" }, callerPrincipal: Drupe::OAuthUser::"alice", callerResource: Drupe::Gateway::"gw1", requestId: "u1")
@100 scope(principal: Drupe::OAuthUser::"alice", resource: Drupe::Gateway::"gw1") request_context(input: { document: "doc1", user: "alice" }) Drupe::Action::"Write"::request(input: { document: "doc1", user: "alice" }, callerPrincipal: Drupe::OAuthUser::"alice", callerResource: Drupe::Gateway::"gw1", requestId: "u2")
@200 scope(principal: Drupe::OAuthUser::"bob", resource: Drupe::Gateway::"gw1") request_context(input: { document: "doc2", user: "bob" }) Drupe::Action::"Write"::request(input: { document: "doc2", user: "bob" }, callerPrincipal: Drupe::OAuthUser::"bob", callerResource: Drupe::Gateway::"gw1", requestId: "u3")
Expected Output
@0 (time point 0): ALLOW [rules: 0]
@100 (time point 1): ALLOW [rules: 0]
@200 (time point 2): DENY