1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# Serbero sample configuration.
#
# Usage:
# 1. Copy this file to `config.toml`
# 2. Replace the placeholder hex keys / relay URLs / solver pubkeys
# 3. Export secrets through environment variables instead of committing them
#
# The daemon loads `./config.toml` by default, or the path set in
# `SERBERO_CONFIG`.
[]
# Hex-encoded Nostr private key for the Serbero daemon identity.
# Production deployments should prefer `SERBERO_PRIVATE_KEY`.
= "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
# SQLite database path. Can be overridden with `SERBERO_DB_PATH`.
= "serbero.db"
# Tracing log level / filter. Can be overridden with `SERBERO_LOG`.
= "info"
[]
# Hex-encoded public key of the Mostro instance to monitor.
= "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"
[[]]
= "wss://relay.example.com"
# Add as many relays as needed.
[[]]
= "wss://relay.backup.example.com"
# Solvers notified for dispute events.
# `permission` is parsed today and becomes more relevant in later phases.
[[]]
= "1111111111111111111111111111111111111111111111111111111111111111"
= "read"
[[]]
= "2222222222222222222222222222222222222222222222222222222222222222"
= "write"
[]
# Re-notify disputes left in `notified` state for this long.
= 300
# How often to scan for unattended disputes.
= 60
# ---------------------------------------------------------------------------
# Phase 3: guided mediation
# Omit or keep disabled to run only Phase 1 / 2 behavior.
# ---------------------------------------------------------------------------
[]
= false
# Maximum mediation rounds before `round_limit` escalation.
= 2
# Escalate if a party does not respond within this many seconds.
# Set to 0 to disable the timeout sweep.
= 1800
# Solver-auth revalidation loop.
= 60
= 3600
= 86400
= 24
[]
= false
# Phase 3 currently ships the OpenAI-compatible adapter.
= "openai"
# Any model accepted by the configured OpenAI-compatible endpoint.
= "gpt-5"
# Hosted OpenAI example. Replace with any OpenAI-compatible endpoint if needed.
= "https://api.openai.com/v1"
# Name of the environment variable holding the reasoning API credential.
# Example:
# export SERBERO_REASONING_API_KEY="your-real-key"
= "SERBERO_REASONING_API_KEY"
# Per-request timeout and bounded retry budget.
= 30
= 1
[]
# Default prompt bundle paths shipped in this repository.
= "./prompts/phase3-system.md"
= "./prompts/phase3-classification.md"
= "./prompts/phase3-escalation-policy.md"
= "./prompts/phase3-mediation-style.md"
= "./prompts/phase3-message-templates.md"
[]
# Inbound Mostro chat polling interval used by the mediation engine.
= 10
# --- Phase 4: escalation execution surface (FR-215) ---
# Consumes Phase 3's handoff_prepared audit events and dispatches
# a structured DM to write-permission solvers. See
# specs/004-escalation-execution/contracts/config.md for the full
# shape.
[]
# Feature flag. `true` spawns the Phase 4 dispatcher task; `false`
# keeps Phase 4 entirely inert (no task, no writes, no Phase 1/2/3
# behavior change). Default: false — Phase 4 is opt-in.
= false
# Scan cadence. Positive integer seconds. The SC-201 target (95% of
# handoffs delivered within 60 s) assumes the default 30 here;
# larger values degrade delivery latency linearly.
= 30
# When zero solvers with `permission = "write"` are configured:
# true → broadcast the handoff DM to every configured solver
# regardless of permission.
# false → refuse to broadcast and record an
# `escalation_dispatch_unroutable` audit event + ERROR log
# line. The handoff stays pending so a later config
# change (adding a write solver) re-surfaces it.
# Operators running intentionally read-only deployments must opt in
# explicitly by flipping this to true.
= false