- Bumped the version of the `lol.mleku.dev` dependency from v1.0.3 to v1.0.4.
- Removed redundant checks for disabled policy in event handling.
- Introduced a `default_policy` field in the policy configuration, allowing for more flexible event handling based on default behaviors.
- Enhanced documentation to clarify the default policy logic and its implications on event processing.
- Updated tests to validate the new default policy behavior and ensure correct fallback mechanisms are in place.
@ -17,6 +17,7 @@ The policy configuration is loaded from `$HOME/.config/ORLY/policy.json`. See `d
@@ -17,6 +17,7 @@ The policy configuration is loaded from `$HOME/.config/ORLY/policy.json`. See `d
```json
{
"default_policy": "allow",
"kind": {
"whitelist": [1, 3, 5, 7, 9735],
"blacklist": []
@ -48,6 +49,17 @@ The policy configuration is loaded from `$HOME/.config/ORLY/policy.json`. See `d
@@ -48,6 +49,17 @@ The policy configuration is loaded from `$HOME/.config/ORLY/policy.json`. See `d
}
```
### Default Policy
The `default_policy` field determines the default behavior when no specific rules deny an event:
- `"allow"` (default): Events are allowed unless explicitly denied by rules
- `"deny"`: Events are denied unless explicitly allowed by rules
This applies to:
- Events of whitelisted kinds that have no specific rules
- Events that pass all other policy checks but have no explicit allow/deny decision
### Policy Evaluation Order
The policy system evaluates events in the following order:
@ -56,6 +68,7 @@ The policy system evaluates events in the following order:
@@ -56,6 +68,7 @@ The policy system evaluates events in the following order:
2. **Kinds Filtering** - Whitelist/blacklist by event kind
3. **Kind-specific Rules** - Rules for specific event kinds
5. **Default Policy** - Applied when no rules make a decision
### Global Rules
@ -173,17 +186,41 @@ When policy is enabled, every EVENT envelope is checked using `CheckPolicy("writ
@@ -173,17 +186,41 @@ When policy is enabled, every EVENT envelope is checked using `CheckPolicy("writ
When policy is enabled, every event returned in REQ responses is filtered using `CheckPolicy("read", event, loggedInPubkey, ipAddress)` before being sent to the client. The same evaluation order applies for read access.
## Error Handling
## Script Resilience
The policy system is designed to be resilient to script failures:
- If policy script fails or times out, events are allowed by default
- If policy configuration is invalid, default policy (allow all) is used
- Policy script failures are logged but don't block relay operation
### Automatic Recovery
- Policy scripts are automatically restarted if they crash or fail to load
- The system continuously monitors script health and attempts recovery every 60 seconds (1 minute)
- Script failures don't disable the entire policy system
### Fallback Behavior
When a policy script fails or is not running:
- Events that would have been processed by the script fall back to the `default_policy`
- The system logs which policy rule is inactive and the fallback behavior
- Other policy rules (global, kinds, non-script rules) continue to function normally
### Error Handling
- If policy script fails or times out, events fall back to `default_policy` setting
- If policy configuration is invalid, default policy (allow all) is used
- Policy script failures are logged with specific rule information but don't block relay operation
## Monitoring
Policy decisions are logged at debug level:
Policy decisions and script health are logged:
### Policy Decisions
- `policy allowed event <id>`
- `policy rejected event <id>`
### Script Health
- `policy rule for kind <N> is inactive (script not running), falling back to default policy (<policy>)`
- `policy rule for kind <N> failed (script processing error: <error>), falling back to default policy (<policy>)`
- `policy rule for kind <N> returned unknown action '<action>', falling back to default policy (<policy>)`
- `policy script not found at <path>, will retry periodically`
- `policy script crashed - events will fall back to default policy until restart`
- `policy filtered out event <id> for read access`
// Kinds defines the filter for events by kind; the whitelist overrides the blacklist if it has any fields, and the blacklist is ignored (implicitly all not-whitelisted are blacklisted)
// Kinds defines whitelist and blacklist policies for event kinds.
// Whitelist takes precedence over blacklist - if whitelist is present, only whitelisted kinds are allowed.
// If only blacklist is present, all kinds except blacklisted ones are allowed.
typeKindsstruct{
// Whitelist is a list of event kinds that are allowed to be written to the relay. If any are present, implicitly all others are denied.
Whitelist[]int`json:"whitelist,omitempty"`
@ -28,13 +30,16 @@ type Kinds struct {
@@ -28,13 +30,16 @@ type Kinds struct {
Blacklist[]int`json:"blacklist,omitempty"`
}
// Rule is a rule for an event kind.
// Rule defines policy criteria for a specific event kind.
//
// If Script is present, it overrides all other criteria.
// Rules are evaluated in the following order:
// 1. If Script is present and running, it determines the outcome
// 2. If Script fails or is not running, falls back to default_policy
// 3. Otherwise, all specified criteria are evaluated as AND operations
//
// The criteria have mutual exclude semantics on pubkey white/blacklists, if whitelist has any fields, blacklist is ignored (implicitly all not-whitelisted are blacklisted).
//
// The other criteria are evaluated as AND operations, everything specified must match for the event to be allowed to be written to the relay.
// For pubkey allow/deny lists: whitelist takes precedence over blacklist.
// If whitelist has entries, only whitelisted pubkeys are allowed.
// If only blacklist has entries, all pubkeys except blacklisted ones are allowed.
typeRulestruct{
// Description is a human-readable description of the rule.
Descriptionstring`json:"description"`
@ -66,14 +71,16 @@ type Rule struct {
@@ -66,14 +71,16 @@ type Rule struct {
// CheckPolicy checks if an event is allowed to be written to the relay based on the policy. The access parameter is either "write" or "read", write is for accepting events and read is for filtering events to send back to the client.
// CheckPolicy checks if an event is allowed based on the policy configuration.
// The access parameter should be "write" for accepting events or "read" for filtering events.
// Returns true if the event is allowed, false if denied, and an error if validation fails.
// Policy evaluation order: global rules → kind filtering → specific rules → default policy.