// who can compose#
Verified callers, oracles, and admins can fire signals from /caller/new. The page is middleware-gated; members and visitors get a redirect.
Until the Sage backend's POST /api/dashboard/caller/signals receive endpoint ships, every fire from the dashboard is mocked end-to-end — the dashboard returns a success envelope with mockOnly:true and nothing actually posts to Discord. The compose form's success panel surfaces this flag explicitly so you know what mode you're in.
// pasting a market#
The market identifier field accepts: a full Polymarket URL (https://polymarket.com/event/SLUG or /market/SLUG), a full Kalshi URL (https://kalshi.com/markets/TICKER), or a bare slug / ticker.
When you paste a /event/ URL the form switches to event-kind and a debounced live-preview fetch from the Sage backend (250ms after you stop typing) shows the child outcomes as chips. Picking a chip auto-fills the outcomeChildSlug.
If the slug is in the dashboard's cached top-250 markets the resolve block shows yes price + 24h vol + ends-in. Otherwise it falls to a 'pending' state — the bot resolves the slug against the venue API at fire time.
// the conviction triplet#
Confidence (low / med / high) — informational vs strong edge. Drives subscriber sizing decisions but does not gate posting.
Recommended size (tracker / standard / conviction / whale) — book-percentage suggestion: 1–2% / 3–5% / 5–10% / >10%. Subscribers with auto-copy on use this to scale.
Time horizon (intraday / short / medium / long) — close-in-24h / ~1 week / 1–4 weeks / until resolution. Helps subscribers decide if a call fits their style.
// distribution — three orthogonal knobs#
Channel — where the post lands: public alpha-calls (every member sees it) / fnf-only (FNF+ audience) / dashboard-draft (no Discord post, saved here only).
Notify — who gets a DM: channel only (no DMs, passive) / DM subscribers (your followers get a DM) / urgent · DM all FNF (bypasses quiet hours, DMs every FNF member). The urgent option uses red styling so you can't miss it.
Execution — how subscribers act: manual deep-link (subscribers click through to the venue) or auto-copy eligible (subscribers with auto-copy on for you will execute, subject to their own caps).
// what the server stamps#
Every audit field on a fired signal comes from the request context, never from the body: caller id (from session), caller username (from session), caller tier-at-time (resolved at request time), fired-at timestamp (server clock), source IP (x-forwarded-for first hop), user-agent (capped at 200 chars), session id.
A malicious client can lie about callerUsername in the JSON body — the route handler ignores it. The success panel shows the server-stamped audit row so you can see exactly what was recorded.
