◆ kanex-ai
Loading…
Interactive Brokers Client Services Jun 17 12:40 AM
Message Center Notification
Interactive Brokers ticket response regarding Kanex account messaging.
financial
Joaquín Medina Jun 17 12:34 AM
RE: Re:[## 708 ##] RE: RMA for EXT-4KHD70M
AVIT Vision requests credit memo for destroyed equipment per RMA 708.
vendor
Microsoft Outlook Jun 16 10:36 PM
Undeliverable: FW: TIER 3 Trending Stocks Part 2 (1 New Red Candle): $DELL, $OSCR, $ONDS, $ZETA, $LMND and $TMC (June 17, 2026-daily)
Microsoft Outlook: Undeliverable: FW: TIER 3 Trending Stocks Part 2 (1 New Red
employee high
Interactive Brokers Client Services Jun 16 9:59 PM
Security Notice for User k******8: Verify Log In
Fake Interactive Brokers security alert requesting account verification.
phishing urgent
Microsoft Outlook Jun 16 9:38 PM
Undeliverable: FW: $QCOM (June 17, 2026-daily)
Microsoft Outlook: Undeliverable: FW: $QCOM (June 17, 2026-daily)
employee high
TDhruv Sharma Jun 16 9:05 PM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
personal
Fabiola Hernandez Jun 16 6:55 PM
Tomorrow is Spirit Day – Souvenir T-Shirt Day
Spirit Day reminder: kids invited to wear souvenir t-shirt tomorrow at camp.
family
Derrick Jun 16 6:19 PM
Request for More Info: EXT-USBC2XI-100M - Dual-Host USB 3.2 Gen 1 Extender over CAT6a — USB-C & USB-B Inputs, 100m/328ft
Product inquiry for USB extender; requesting pricing, specs, availability.
vendor
Sydnee Agent (AI) Jun 16 6:00 PM
[Spread Cal] 2026-06-17 — per-stock max_spread_bps results
Sydnee Agent (AI): [Spread Cal] 2026-06-17 — per-stock max_spread_bps results
employee high
Sydnee Agent (AI) Jun 16 5:40 PM
[Calibration Daily] 2026-06-17
Sydnee Agent (AI): [Calibration Daily] 2026-06-17
employee high
Sydnee Agent (AI) Jun 16 5:30 PM
Sydnee algo daily — dev $-2,699 · prod $+0 · 6d window
Sydnee Agent (AI): Sydnee algo daily — dev $-2,699 · prod $+0 · 6d window
employee high
Find My Jun 16 5:24 PM
A sound was played on Kelvin’s iPad mini.
Find My: A sound was played on Kelvin’s iPad mini.
vendor
Sammy Cemo, Matt Pourcho and Anthony DeLorenzo Jun 16 4:04 PM
New Pricing | Fortune 40 Credit | STNL Industrial | 11 Yr. WALT | SoCal
⚠ PHISHING: employee impersonation: display name matches 'anthony' but sender is cbre.com
phishing urgent
Microsoft Store Jun 16 3:23 PM
Meet the new Surface lineup—with limited-time offers
Microsoft Store: Meet the new Surface lineup—with limited-time offers
vendor
[email protected] Jun 16 2:34 PM
New Funding Program
Funding broker offering working capital solutions and consolidation services.
vendor
Sammy Cemo and Anthony DeLorenzo Jun 16 2:03 PM
Single-Story Owner-User Offering in Newport Beach
⚠ PHISHING: employee impersonation: display name matches 'anthony' but sender is cbre.com
phishing urgent
Aarti Gupta Jun 16 1:53 PM
Re: CR-TOUCH6R 6" Widescreen Touch Panel with Knob, RS232/RS485 & PoE
Aarti Gupta: Re: CR-TOUCH6R 6" Widescreen Touch Panel with Knob, RS232/RS
employee high
[email protected] Jun 16 1:43 PM
Action required: Your June booking bonuses expire soon
⚠ PHISHING: phishing subject pattern: 'Action required' from external sender vacationoffer.com
phishing urgent
TAnthony Patino Jun 16 1:30 PM
[Teams oneOnOne] (Teams DM)
LK account overdrawn; bank fee applied, needs replenishment before QB charge.
employee high
TAnthony Patino Jun 16 1:27 PM
[Teams oneOnOne] (Teams DM)
Anthony Patino sent a brief Teams DM referencing 'LK'.
employee
TAnthony Patino Jun 16 1:27 PM
[Teams oneOnOne] (Teams DM)
Anthony Patino reports insufficient funds issue.
employee high
Amazon Payments Jun 16 12:44 PM
Action requise sur le compte Amazon Payments
Fake Amazon Payments suspension notice in French requesting account verification.
phishing urgent
Nick Daniel Jun 16 11:04 AM
Quick question
TriNet HR solution sales inquiry.
vendor low
Aarti Gupta Jun 16 10:04 AM
Re: Order help #1227
Aarti Gupta: Re: Order help #1227
employee high
Aarti Gupta Jun 16 10:03 AM
Re: Order help #1227
Aarti Gupta: Re: Order help #1227
employee high
Aarti Gupta Jun 16 9:59 AM
EXT-USBCPD4K-70M 18Gbps USB-C 4K60 HDBaseT 3.0 Extender with 100W PD (70m)
Aarti Gupta: EXT-USBCPD4K-70M 18Gbps USB-C 4K60 HDBaseT 3.0 Extender with
employee high
Sean McGinley Jun 16 9:58 AM
Order help #1227
Customer inquiry about HDMI extender transmitter compatibility for order #1227.
vendor
IBKR FYI Jun 16 9:51 AM
FYI: Upcoming Exchange Holidays
Exchange holiday notice: MIAX, NASDAQ, NYSE closed June 19.
financial low
IBKR FYI Jun 16 9:27 AM
FYI: Upcoming Exchange Holidays
NASDAQ/MIAX exchange holiday June 19, 2026 — no trading.
financial low
Hims Jun 16 9:02 AM
Kelvin - action required on your account
⚠ PHISHING: phishing subject pattern: 'action required' from external sender icloud.com
phishing urgent
[email protected] Jun 16 9:02 AM
You have a new estimate
Suspicious medical estimate link from Providence—verify legitimacy before clicking.
phishing urgent
Mail Delivery System Jun 16 8:20 AM
Mail delivery failed [Invoice #36077 PO: SH260526762J]
Mail delivery failed for invoice #36077 to Mike Vanderkamp; recipient address rejected.
financial
Mail Delivery System Jun 16 8:19 AM
Mail delivery failed [Invoice #36078 PO: SH260430677J]
Mail delivery failed: [email protected][email protected] for invoice #36078.
vendor
Mail Delivery System Jun 16 8:19 AM
Mail delivery failed [Invoice #36079 PO: SH2606101007J]
Mail delivery failure: invoice to [email protected] rejected by recipient server.
financial
TDhruv Sharma Jun 16 8:16 AM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
personal
Zoho Campaigns Jun 16 7:55 AM
Campaign "NEW USB-C + USB-B Dual-Host Extender · 100m" has been successfully Sent - Zoho Campaigns
Zoho Campaigns notification: USB-C/USB-B extender product campaign sent successfully.
employee
Ali Pacheco Jun 16 7:53 AM
Request for More Info: EXT-USBC2XI-100M - Dual-Host USB 3.2 Gen 1 Extender over CAT6a — USB-C & USB-B Inputs, 100m/328ft
Product inquiry for USB 3.2 extender from external vendor.
vendor
KanexPro Jun 16 7:51 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
employee high
KanexPro Jun 16 7:50 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
employee high
KanexPro Jun 16 7:50 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
employee high
KanexPro Jun 16 7:49 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
employee high
TDhruv Sharma Jun 16 7:33 AM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
personal
TDhruv Sharma Jun 16 7:32 AM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
personal
Bank of America Jun 16 6:16 AM
Your available account balance is low
Bank of America: Your available account balance is low
financial
Let's Talk Supply Chain Jun 16 6:01 AM
Are you ready?
Suspicious meeting confirmation from unknown sender with obfuscation.
phishing urgent
Interactive Brokers Client Services Jun 16 5:18 AM
Message Center Notification
Interactive Brokers ticket response regarding Kanex account notification.
financial
Benjamin & Williams Jun 16 5:03 AM
Commercial Claim Discovery Documents Our file:D-8222 Debtor: VICTORIA ROPA ELEGANTE
Fake debt collector demanding payment on unknown commercial claim within 24h.
phishing urgent
IBKR FYI Jun 16 5:01 AM
FYI: Option Expiration Notification
Oracle options expiring 18JUN2026 — immediate action required.
financial high
IBKR FYI Jun 16 5:00 AM
FYI: Option Expiration Notification
MSTR call option expiring 18JUN2026; action needed if extending position.
financial
Sydnee Agent (AI) Jun 16 4:25 AM
Sydnee nightly — exit_flow audit 2026-06-16 — 0P0 8P1 6R
Sydnee Agent (AI): Sydnee nightly — exit_flow audit 2026-06-16 — 0P0 8P1 6R
employee high

Sydnee WEEKLY (cross-cutting) audit 2026-05-31 — 0P0 0P1 0R

Sydnee Agent (AI) <[email protected]>
To: Kelvin Yan <[email protected]>
Sunday May 31, 2026 · 3:20 AM PT · in [email protected]
AI verdict  employee high · confidence: high · by internal-exempt
“Sydnee Agent (AI): Sydnee WEEKLY (cross-cutting) audit 2026-05-31 — 0P0 0P1 0R”
Reasoning: @sydnee.ai is a protected domain — hard exemption
Sydnee WEEKLY (cross-cutting) audit — 2026-05-31 P0 findings: 0 P1 findings: 0 Risks: 0 - **Commits since last weekly (2026-05-24):** 39 code/feature commits + 7 daily-audit docs (excluding 115 peak-monitor hourly logs) - **Files changed:** `bot.py`, `pages.py`, `core/database.py` - **Major new work:** TV-BXt v2 (spread gate, WS-touch pricing, order-flow confirmation, IP allowlist, disable-algo-stops flag), reconcile avgCost sanity-check + quarantine 25%→55%, Phase-0 tape-scanner + scalp edge logger, OBV-trail dashboard history | Category | Count | |---|---| | P1 (carried) | 3 | | P1 (new) | 1 | | P2 (new) | 2 | | Doc drift (carried) | 2 | | Doc drift (new) | 1 | | **Fixed this week** | 0 (no carried items resolved) | --- Full report (dev branch): https://github.com/kanex1/sydnee.signals/blob/dev/docs/audit_2026-05-31_weekly.md Reply FROM [email protected] to [email protected] to request fixes, e.g.: "code_task on sydnee-signals-dev: apply fix for the P0 about RVOL threshold in bot.py" Sydnee Agent will propose + you APPROVE (or plain 'approve') + auto-push to dev. --- Full audit below (first 12 KB) --- # Weekly Code Audit 2026-05-31 ## Summary - **Commits since last weekly (2026-05-24):** 39 code/feature commits + 7 daily-audit docs (excluding 115 peak-monitor hourly logs) - **Files changed:** `bot.py`, `pages.py`, `core/database.py` - **Major new work:** TV-BXt v2 (spread gate, WS-touch pricing, order-flow confirmation, IP allowlist, disable-algo-stops flag), reconcile avgCost sanity-check + quarantine 25%→55%, Phase-0 tape-scanner + scalp edge logger, OBV-trail dashboard history | Category | Count | |---|---| | P1 (carried) | 3 | | P1 (new) | 1 | | P2 (new) | 2 | | Doc drift (carried) | 2 | | Doc drift (new) | 1 | | **Fixed this week** | 0 (no carried items resolved) | --- ## Fixed Since Last Weekly (2026-05-24) None of the P1s from the 2026-05-24 weekly were addressed this week. All three carry forward (see Findings below). --- ## Findings --- ### [CONFIG] P1 (new): `TV_BXT_TRAIL_AGAINST` has two different defaults in the same file **Files:** `bot.py:3750`, `bot.py:14062` **Evidence:** ```python # bot.py:3750 — _obv_trail_stop_hit (LIVE TRADING path): agnst = float(os.environ.get("TV_BXT_TRAIL_AGAINST", "1.0")) # bot.py:14062 — api_trade_obv_trail (history REPLAY endpoint): agnst = float(os.environ.get("TV_BXT_TRAIL_AGAINST", "1.5")) ``` When `TV_BXT_TRAIL_AGAINST` is not set in the environment, the live engine uses a `1.0×ATR` against-trend trail, but the OBV-trail history endpoint reconstructs the stop history using `1.5×ATR`. Every closed-trade timeline shown on the dashboard shows a tighter stop than what actually ran — the replay cannot accurately reproduce the stop sequence that was live. The discrepancy was almost certainly introduced when the history endpoint was added as a copy of the live path with different defaults. The live default (`1.0`) matches `strategy_decisions.md` ("tight 1×ATR when OBV turns"). **Impact:** Historical stop-analysis data on the trade card is wrong whenever the env var is unset (the default path). Could cause incorrect post-trade analysis conclusions ("the stop was too tight/wide" when it wasn't). **Recommendation:** Change `bot.py:14062` to `"1.0"` to match the live default. One-line fix. --- ### [SECURITY] P1 (carried 5 weeks — 2026-05-03 → 2026-05-31): Hardcoded `"8881"` API key in client-side JavaScript **Files:** `pages.py:6865`, `pages.py:7109`, `pages.py:7673`, `pages.py:7960`, `pages.py:7965`, `pages.py:7968` **Evidence:** ```js // pages.py:6865 — stock add fetch('/api/stocks/add', {headers: {'X-API-Key': '8881'}, ...}) // pages.py:7109 — screener scan apiPost("/api/screener/run", {password: "8881", ...}) // pages.py:7673 — cancel order fetch("/api/positions/cancel", {headers: {"X-API-Key": "8881"}, ...}) // pages.py:7960, 7965, 7968 — QA approve/reject/defer apiPost('/api/qa/suggestion/'+id, {action:'approved', password:'8881'}) ``` Server: `API_KEY = os.environ.get("API_KEY", "8881")` (bot.py:11140). If `API_KEY` is rotated, all six JS actions break silently with 401. The literal `"8881"` is visible in every page source load. **Impact:** Credential in plain-text page source; rotation breaks six write features; weak 4-digit default. **Recommendation:** Pass key via Jinja2 template variable: `render_template_string(PAGE_HTML, api_key=API_KEY)` and replace the six literals with `{{ api_key }}`. ~15 min fix. --- ### [SCHEMA] P1 (carried 5 weeks — 2026-05-03 → 2026-05-31): 5 tables + 2 columns missing from `core/schema.sql` **Files:** `core/database.py:1852`, `1891`, `1903`, `2003`, `2024`; `core/database.py:230-231`; `core/schema.sql` **Evidence (tables):** ```python # core/database.py — INSERT INTO tables with no CREATE TABLE in schema.sql: # :1852 change_requests # :1891 qa_reports # :1903 qa_suggestions # :2003 screener_results # :2024 screener_runs ``` **Evidence (columns added via ALTER TABLE, not in schema.sql):** ```python # core/database.py:230-231 "ALTER TABLE trades ADD COLUMN IF NOT EXISTS tick_peak_signed_vol BIGINT DEFAULT 0" "ALTER TABLE trades ADD COLUMN IF NOT EXISTS fri_ah_close_queued BOOLEAN DEFAULT FALSE" ``` `grep "change_requests\|qa_report\|qa_suggest\|screener_result\|screener_run\|tick_peak_signed_vol\|fri_ah_close_queued" core/schema.sql` → zero results. **Impact:** Fresh DB provision (staging reprovision, new dev environment) silently produces a different schema than what the code expects. The `IF NOT EXISTS` guard on ALTER TABLEs means the running instance is fine, but any new deploy starts broken without visible errors (`_safe()` wrappers swallow them). **Recommendation:** Add the 5 missing `CREATE TABLE IF NOT EXISTS` blocks (copy column lists from the INSERT statements) and add the 2 missing columns to the `trades` block in schema.sql. Convention to establish: any `ALTER TABLE ADD COLUMN IF NOT EXISTS` in database.py also gets reflected in schema.sql in the same commit. --- ### [SCHEMA] P2 (new): `scalp_signal_log` table absent from `core/schema.sql` **Files:** `core/database.py:300-331`; `core/schema.sql` **Evidence:** ```python # core/database.py:300-331 — ensure_scalp_signal_log_table(): CREATE TABLE IF NOT EXISTS scalp_signal_log ( id BIGSERIAL PRIMARY KEY, ts TIMESTAMPTZ NOT NULL, symbol VARCHAR(12) NOT NULL, ... ) ``` `grep "scalp_signal_log" core/schema.sql` → zero results. The table is created dynamically when `SCALP_SIGNAL_LOG=true` via `ensure_scalp_signal_log_table()` (called at loop startup, bot.py:16107). That's robust at runtime. But schema.sql does not document the table, continuing the pattern of schema drift that the 5-table P1 above represents. **Impact:** Schema documentation drift. Any engineer reading schema.sql to understand the DB structure will miss this table. Fresh provision without ever enabling `SCALP_SIGNAL_LOG` won't have the table, so the `/api/scalp-signal-log/summary` endpoint will 500 on a fresh instance if called before the flag is set. **Recommendation:** Add the `scalp_signal_log` CREATE TABLE to schema.sql (copy from database.py:310-330). Makes schema.sql the single source of DB truth again. --- ### [SECURITY] P2 (new): TV webhook IP allowlist is bypassable via `X-Forwarded-For` header spoofing **Files:** `bot.py:3592-3598`, `bot.py:12222-12227` **Evidence:** ```python # bot.py:3596-3598 — takes the FIRST XFF entry: xff = req.headers.get("X-Forwarded-For", "") if xff: return xff.split(",")[0].strip() # bot.py:11107 — ProxyFix already set: app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1) ``` `ProxyFix(x_for=1)` tells Werkzeug to trust ONE proxy hop — it correctly sets `request.remote_addr` to the actual client IP by consuming the rightmost XFF entry added by Traefik. However, `_tv_webhook_client_ip` bypasses ProxyFix and re-parses XFF manually, taking the FIRST (leftmost) entry. An attacker can prepend a TV relay IP to their request's `X-Forwarded-For` header (e.g. `X-Forwarded-For: 52.89.214.238`); Traefik appends the real IP to the right, making it `52.89.214.238, real.attacker.ip`. The function returns `52.89.214.238` → allowlist check passes. The secret check (`_secrets.compare_digest`, bot.py:12219) runs BEFORE the IP check and is not bypassed — this only matters if the secret is also compromised. **Impact:** Defense-in-depth bypass only. If the secret is rotated correctly the IP spoofing provides no additional leverage. If the secret leaks, an attacker from any IP can spoof the TV relay IPs to avoid the allowlist log noise. **Recommendation:** Replace the manual XFF parse in `_tv_webhook_client_ip` with `return req.remote_addr or ""` — ProxyFix has already done the right thing. One-line fix, no behavior change in the normal path. --- ### [DOC] P2 (new): 9 env vars added this week have no entry in CLAUDE.md **Files:** `bot.py:3967`, `bot.py:3589`, `bot.py:4000`, `bot.py:4016-4018`, `bot.py:14162`, `bot.py:16100`, `bot.py:16110-16112` **Evidence:** `grep -n "TV_BXT_DISABLE_ALGO_STOPS\|TV_BXT_FLOW_CONFIRM\|TV_BXT_FLOW_RATIO_MIN\|TV_BXT_FLOW_MIN\|TV_BXT_VOL_MIN\|TV_WEBHOOK_ALLOWED_IPS\|SCALP_SIGNAL_LOG\|TAPE_SCANNER_SYMBOLS" CLAUDE.md` → zero results. | Env var | Default | Effect | |---|---|---| | `TV_BXT_DISABLE_ALGO_STOPS` | `""` (stops ON) | Disables catastrophic + OBV-trail stops for TV model entirely | | `TV_BXT_FLOW_CONFIRM` | `""` (off) | Enables 1-min order-flow confirmation gate before entry | | `TV_BXT_FLOW_RATIO_MIN` | `0` (off) | Min imbalance ratio \|net_flow\|/vol to confirm entry (~0.15 = mild) | | `TV_BXT_FLOW_MIN` | `0` (off) | Absolute min signed volume floor for flow gate | | `TV_BXT_VOL_MIN` | `0` (off) | Absolute min total volume floor for flow gate | | `TV_WEBHOOK_ALLOWED_IPS` | TV's 4 relay IPs | Override TradingView IP allowlist; empty = secret-only auth | | `SCALP_SIGNAL_LOG` | `""` (off) | Enable Phase-0 tape-checklist edge logger (no trading) | | `TAPE_SCANNER_SYMBOLS` | `""` (full watchlist) | Pin tape-scanner to specific symbols instead of full watchlist | | `SCALP_SIGNAL_LOG_SEC` | `2.0` | Scan cadence in seconds for the scalp logger | | `SCALP_SIGNAL_LOG_MIN_SCORE` | `3` | Minimum 4-signal checklist score to log (3 or 4) | | `SCALP_SIGNAL_LOG_COOLDOWN_SEC` | `60` | Per-symbol cooldown between logged events | **Impact:** An operator debugging a production issue (or an AI session) won't know `TV_BXT_DISABLE_ALGO_STOPS` exists — this is a stop-loss kill switch that could be accidentally left set without anyone noticing. The CLAUDE.md BXt env-var table (already flagged in the 2026-05-24 weekly as incomplete) has grown 9 more gaps this week. **Recommendation:** Add these 9 vars to the BXt env-var reference table in CLAUDE.md. `TV_BXT_DISABLE_ALGO_STOPS` in particular should be highlighted as a kill switch (not a tuning param). --- ### [DOC] P2 (carried 2 weeks): CLAUDE.md Architecture section stale **Files:** `CLAUDE.md:6-11`, `CLAUDE.md:75-80` **Evidence (3 sub-issues, same as 2026-05-24 weekly):** - `CLAUDE.md:6`: "bot.py ~10K lines" → actual 18,140 lines (80% wrong); `pages.py` = 10,762 lines, not mentioned in Architecture at all. - `CLAUDE.md:75-80` Dev-Only section: "Production: IBKR for everything (no env var set)" directly contradicts Architecture-section note `USE_POLYGON_DATA=true on both dev and prod`. Both sections are in the same file. - Oracle sidecar (`oracle/service.py`, `Dockerfile.oracle`), the 4-way BXt model selector, the scanner page, and Phase-0 scalp logger remain absent from the Architecture section. **Impact:** Two-sentence contradiction in the same file about whether prod uses Polygon. Any session following the dev-only blurb will assume prod has no Polygon and waste time debugging. **Recommendation (10-min fix):** 1. `CLAUDE.md:6`: update line count to "bot.py ~18K lines"; add `pages.py` (~11K lines). 2. `CLAUDE.md:75-80`: delete the Polygon bullet from Dev-Only Features (correct description already in Architecture section above it). 3. Add one sentence under Architecture: "Phase-0 tape-checklist scanner page (`/scanner`) + scalp edge logger (`SCALP_SIGNAL_LOG`) — research-only, no auto-trading." --- ### [DOC] P2 (carried 3 weeks): Friday EOD cutoff absent from CLAUDE.md Entry Time Blockers table **Files:** `CLAUDE.md:40-45`, `bot.py:4552-4558` **Evidence:** ```python # bot.py:4552-4558 — fires for ALL trigger types including rsi_extreme: if now_et.weekday() == 4 and t_min >= 15 * 60: self._log_activity(sym, "FRI CUTOFF: no new entries Friday after 12:00 PM PT", "block") return ``` The Entry Time Blockers table in CLAUDE.md has no Friday row. The "Net effect" summary says RSI extreme runs nearly 24×5 (with only the overnight and RTH-open gaps), implying it runs Friday PM — it doesn't. **Recommendation:** Add one row to the Entry Time Blockers table: ``` | Fri 12:00 PT (15:00 ET) onward | **all entries blocked** (weekend gap risk) | ALL triggers | ``` And update the Net effect line to note the Friday cutoff. --- ## OK (spot-checked, clean) - **New endpoint auth coverage**: `/api/tape-scanner`