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

desk_governance

A four-policy trading-desk set combining most of the language in one place:

  1. permit_sell_open_session_rate_limited — a trader may sell only with an open session (!Logout since Login), an approval for the same stock within the last hour (formerly), and at most three sales in the last hour (a count rate limit).
  2. forbid_insider_notes — a provider guardrail: the Text::Scan information provider (providers.json) flags notes mentioning “insider”.
  3. forbid_sell_amzn — a deny-overrides carve-out for AMZN.
  4. permit_admin_approve — an admin may approve a sale for any stock except one they themselves requested to sell in the last hour.

The trace follows alice (all events are hers, as the default event schema correlates history to the requesting principal):

  • @0 — alice logs in (a Login response, history only).
  • @60 — her MSFT sale is approved (an ApproveSale response, history only).
  • @120 — alice sells MSFT → allow (open session, approved, first sale).
  • @180 — alice sells AMZN → deny (forbid_sell_amzn; there is also no AMZN approval).
  • @240 — alice sells MSFT with notes mentioning an insider tip → deny (forbid_insider_notes).
  • @300 — alice logs out → deny (no rule permits Logout; the request is still recorded in the history).
  • @360 — alice sells MSFT again → deny: her session is closed (a Logout since the Login), and this would also be her fourth sale within the hour.

Policy

// A trading-desk governance set. Deny-overrides: the forbids win over any permit.

// 1. Permit a share sale only for a trader with an OPEN session (logged in and
//    not since logged out) who has NOT sold more than 3 times in the last hour,
//    and whose sale was approved for the same stock within the last hour.
@id("permit_sell_open_session_rate_limited")
permit ( principal is Desk::OAuthUser, action == Desk::Action::"SellShares", resource )
when temporal {
    !Desk::Action::"Logout"::request{ input.user: context.input.user }
    since within 8h
    Desk::Action::"Login"::response{ input.user: context.input.user, output.result: true }
}
when temporal {
    formerly within 1h Desk::Action::"ApproveSale"::response{
        input.user: context.input.user,
        input.stock: context.input.stock,
        output.approved: true
    }
}
when temporal {
    exists (n: Long). (
        (count for (t: Timepoint). where (
            formerly within 1h (Desk::Action::"SellShares"::request{ input.user: context.input.user } && tp(t))
        )) == n
        && n <= 3
    )
};

// 2. Never permit a sale whose notes look like insider-trading chatter
//    (computed by a content-scanning information provider).
@id("forbid_insider_notes")
forbid ( principal, action == Desk::Action::"SellShares", resource )
when { Text::Scan(context.input.notes).flagged == true };

// 3. Never permit selling AMZN, regardless of everything else.
@id("forbid_sell_amzn")
forbid ( principal, action == Desk::Action::"SellShares", resource )
when { context.input.stock == "AMZN" };

// 4. An admin (an IAM entity) may approve a sale for any stock except one they
//    themselves requested to sell in the last hour.
@id("permit_admin_approve")
permit ( principal is Desk::IamEntity, action == Desk::Action::"ApproveSale", resource )
when temporal {
    !Desk::Action::"SellShares"::request{ input.user: context.input.user, input.stock: context.input.stock }
    since within 1h
    Desk::Action::"Login"::response{ input.user: context.input.user }
};

Schema

namespace Desk {
  entity Gateway;
  entity OAuthUser = { id: String, desk: String } tags String;
  entity IamEntity = { id: String };

  type LoginInput  = { user: String };
  type LoginOutput = { result: Bool };

  type LogoutInput = { user: String };

  type ApproveInput  = { user: String, stock: String };
  type ApproveOutput = { approved: Bool };

  type SellInput  = { user: String, stock: String, shares: Long, notes: String };
  type SellOutput = { proceeds: decimal };

  action "Login" appliesTo {
    principal: [OAuthUser, IamEntity],
    resource: [Gateway],
    context: { input: LoginInput, output?: LoginOutput }
  };

  action "Logout" appliesTo {
    principal: [OAuthUser, IamEntity],
    resource: [Gateway],
    context: { input: LogoutInput }
  };

  action "ApproveSale" appliesTo {
    principal: [OAuthUser, IamEntity],
    resource: [Gateway],
    context: { input: ApproveInput, output?: ApproveOutput }
  };

  action "SellShares" appliesTo {
    principal: [OAuthUser, IamEntity],
    resource: [Gateway],
    context: { input: SellInput, output?: SellOutput }
  };
}

Trace

@0 scope(principal: Desk::OAuthUser::"alice", resource: Desk::Gateway::"gw1") Desk::Action::"Login"::response(input: { user: "alice" }, output: { result: true }, callerPrincipal: Desk::OAuthUser::"alice", callerResource: Desk::Gateway::"gw1", requestId: "u1")
@60 scope(principal: Desk::OAuthUser::"alice", resource: Desk::Gateway::"gw1") Desk::Action::"ApproveSale"::response(input: { user: "alice", stock: "MSFT" }, output: { approved: true }, callerPrincipal: Desk::OAuthUser::"alice", callerResource: Desk::Gateway::"gw1", requestId: "u2")
@120 scope(principal: Desk::OAuthUser::"alice", resource: Desk::Gateway::"gw1") request_context(input: { user: "alice", stock: "MSFT", shares: 10, notes: "rebalancing" }) Desk::Action::"SellShares"::request(input: { user: "alice", stock: "MSFT", shares: 10, notes: "rebalancing" }, callerPrincipal: Desk::OAuthUser::"alice", callerResource: Desk::Gateway::"gw1", requestId: "u3")
@180 scope(principal: Desk::OAuthUser::"alice", resource: Desk::Gateway::"gw1") request_context(input: { user: "alice", stock: "AMZN", shares: 10, notes: "rebalancing" }) Desk::Action::"SellShares"::request(input: { user: "alice", stock: "AMZN", shares: 10, notes: "rebalancing" }, callerPrincipal: Desk::OAuthUser::"alice", callerResource: Desk::Gateway::"gw1", requestId: "u4")
@240 scope(principal: Desk::OAuthUser::"alice", resource: Desk::Gateway::"gw1") request_context(input: { user: "alice", stock: "MSFT", shares: 10, notes: "insider tip from the CFO" }) Desk::Action::"SellShares"::request(input: { user: "alice", stock: "MSFT", shares: 10, notes: "insider tip from the CFO" }, callerPrincipal: Desk::OAuthUser::"alice", callerResource: Desk::Gateway::"gw1", requestId: "u5")
@300 scope(principal: Desk::OAuthUser::"alice", resource: Desk::Gateway::"gw1") request_context(input: { user: "alice" }) Desk::Action::"Logout"::request(input: { user: "alice" }, callerPrincipal: Desk::OAuthUser::"alice", callerResource: Desk::Gateway::"gw1", requestId: "u6")
@360 scope(principal: Desk::OAuthUser::"alice", resource: Desk::Gateway::"gw1") request_context(input: { user: "alice", stock: "MSFT", shares: 10, notes: "rebalancing" }) Desk::Action::"SellShares"::request(input: { user: "alice", stock: "MSFT", shares: 10, notes: "rebalancing" }, callerPrincipal: Desk::OAuthUser::"alice", callerResource: Desk::Gateway::"gw1", requestId: "u7")

Expected Output

@120 (time point 0): ALLOW  [rules: 0]
@180 (time point 1): DENY  [rules: 2]
@240 (time point 2): DENY  [rules: 1]
@300 (time point 3): DENY
@360 (time point 4): DENY

Provider Declarations

{
  "availableProviders": {
    "Text::Scan": {
      "argumentTypes": [{ "paramType": "string" }],
      "outputType": {
        "paramType": "record",
        "fields": { "flagged": { "paramType": "bool" } },
        "required": ["flagged"]
      },
      "implementation": {
        "kind": "rhai",
        "script": "fn evaluate(text) { if type_of(text) == \"()\" { return #{ flagged: false }; } #{ flagged: regex_count(\"(?i)insider\", text) > 0 } }"
      }
    }
  }
}