Getting started
Add a deterministic L3 guard without moving the main strategy out of SJS.
Start with a working SJS strategy and a saved baseline. This example permits place/modify requests only when their quantity is a finite number greater than zero and no greater than two. It makes no execution requests itself.
Add a separate L3 script
Paste the complete script into the L3 source field, leaving the main algorithm in SJS:
export const config = { enabled: true };
export async function app({ context, bar }) {
const state = (context.l3State ??= {}).requestGuard ??= {};
const timestamp = bar?.date == null ? NaN : new Date(bar.date).getTime();
state.lastMarketTime = Number.isFinite(timestamp) ? timestamp : null;
}
export async function intent({ context, intent, log }) {
const state = (context.l3State ??= {}).requestGuard ??= {};
const checked = ["place_order", "modify_order"].includes(intent?.kind);
const quantity = intent?.options?.order?.quantity;
const allowed = !checked || (
typeof quantity === "number" && Number.isFinite(quantity)
&& quantity > 0 && quantity <= 2
);
state.lastCheck = {
kind: intent?.kind ?? null,
quantity: quantity ?? null,
allowed,
};
log?.("l3-request-guard", state.lastCheck);
return allowed;
}The frame hook records the market time. The intent hook validates the request and returns an explicit Boolean. It can run even if no earlier frame has initialized this script's state.
Exercise the boundary
| Ordinary place/modify quantity | Hook result |
|---|---|
1 or 2 | true |
3, zero, negative, missing, string, or non-finite | false |
Other request kinds return true because they are outside this guard's scope. This is a per-request quantity check, not a cap on total exposure.
Use quantity one in the SJS strategy for the allowed case and three for the rejected case. Keep data and other execution settings fixed. Compare the l3-request-guard log with the SJS attempt and actual order/position result.
Understand the boundaries
Manual requests can override the hook's result in the normal runtime. L3-originated requests bypass the intent hook. The example is not a permissions boundary for those sources.
A shared simulated close can pass its close_position check and then fail the delegated place_order quantity check. Test the complete path when closing more than two units.
Continue with lifecycle, or use your first policy when you want the same idea organized into reusable modules.