Board 2026-09-13 — Autonomous email SOP — CISO draft #150
Closed
opened 2026-09-13 22:58:15 -04:00 by logan
·
1 comment
No Branch/Tag Specified
Labels
Clear labels
area/ai-pipeline
area/auth
area/billing
area/correlation
area/discord
area/frontend
area/governance
area/growth
area/infra-deploy
area/legal
area/map
area/mqtt
area/node-ota
area/osint
area/recording-audio
area/sdr-radio
area/transcription
board
board:agenda
minutes:draft
minutes:final
role:ceo
role:cfo
role:cio
role:ciso
role:cmo
role:coo
role:cto
Scene/entity extraction, summarizer, AI providers, embeddings
AuthN/Z, roles, tenancy/org scoping, API keys, credentials
Plans, entitlements, AI spend accounting and caps
Incident correlation, linking, lifecycle, severity, corr_debug
Discord bot, radio bots, voice streams, bot tokens, webhooks
Web UI: Next.js app and the edge-node local dashboard
Board process, minutes, unattended runner, agent tooling
Go-to-market, outreach, cold email, discovery conversations
CI/CD, VM, registry, Firestore rules/indexes deploy, Terraform/Caddy
ToS, retention, licences/DAAs, CAN-SPAM, E&O, name suppression
Live map: pins, paths, tiles, legend, geocoding
Node-C2 MQTT, checkins, commands, node sweeper, dynsec
Node install, enrollment, OTA updater, image skew
External feeds: cameras, 511, ADS-B, AIS, outages, and their licences
Call capture, boundaries, PulseAudio, ring buffer, trimming, attribution
OP25 decode, SDR hardware/tuning, conventional, second SDR, mesh radio
STT, transcript correction, place verification, name accuracy
Board process: minutes and board-filed items
Needs board scoping at the next sitting; CEO removes the label once scoped
One exec pre-read, closed by CEO
CEO ruling; open until enacted
Filed by the CEO
Filed by the CFO
Filed by the CIO
Filed by the CISO
Filed by the CMO
Filed by the COO
Filed by the CTO
kind
behavior-bug
Wrong product behavior; the instrument reads it correctly
kind
measurement-bug
Corrupts the recording/instrument (debug data, evals, health checks), not behavior
priority
p0
Drop everything: prod broken, live exposure, or owner-ruled P0
priority
p1
Next up: blocks a gate, a customer, or core incident quality
priority
p2
Normal: real defect or planned work, schedule in turn
priority
p3
Low: minor, cosmetic, or someday
status
blocked
Waiting on an external party, spend, or another issue
status
in-progress
Branch or PR open against it
status
needs-decision
Waiting on an owner or board ruling before work
status
needs-info
Root cause or repro unknown; needs a reading first
type
bug
Something built is wrong: code, data, or a measurement
type
chore
Maintenance, refactor, tests, pinning, cleanup: no user-visible change
type
decision
A ruling to make or record: board minutes, owner calls, legal reviews
type
docs
Docs, runbooks, CLAUDE.md, skills, SOPs
type
feature
New capability or an extension of an existing one
type
security
Security, privacy, credential or tenant-isolation exposure
type
tracking
Tracker, checklist, initiative or punch-list spanning several changes
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: logan/server-26#150
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Position
Sending autonomously is buildable safely with code-enforced gates — nothing today implements it, so this is a build spec, not a hardening pass on existing code (
grep -rn "SMTP\|IMAP\|smtplib\|imaplib" Server/ Client/returns zero hits; growth-ops.md's boundary #1 amendment only grants drafting togrowth/outbox/, not sending). Autonomous reply is the higher-risk half, exactly as flagged in the task: it is a live LLM answering a real business owner with zero review, and it needs hard content and behavior boundaries a prompt cannot be trusted to hold alone. I am not re-litigating the owner's autonomy ruling — I am naming the smallest set of code-level gates that make it safe to build, and flagging one place (reply canary review) where I still think a sliver of human eyes belongs, for the owner to overrule if he wants literal zero.Findings
Server/,Client/— zero SMTP/IMAP hits). Whoever builds it will be tempted to give the reply-generation step "context" to sound informed — the single fastest way this becomes the worst incident the company has had: a bot answering "can you show me an example near my shop?" by reaching into Firestorecalls/incidentsand quoting real transcribed police radio traffic tied to a real address and a real name, unreviewed, sent externally. Blast radius: the most sensitive asset the company holds, delivered to a stranger's inbox with no human in the loop and no undo. Fix: the reply service gets zero read path to Firestore, GCS, or any transcript/incident store — only the inbound thread text, the target's directory row, and canned template fragments. This is a network/IAM-level exclusion, not an instruction to the LLM..claude/agents/growth-ops.md:56-91(boundaries #1/#3/#4/#5/#6) are prompt-enforced today, fine for a human-reviewed draft. An autonomous sender removes the human who currently catches a boundary slip before it leaves the building. Fix: pre-send/pre-reply hard checks — footer regex match,growth/suppression-list.mdmembership check, sent-ledger dedupe keyed on recipient email, and a$/price-pattern + incident/talkgroup/address/name-pattern block — each one aborts-and-logs on failure, never sends on ambiguous match.growth/suppression-list.mdand the thread ends — no further autonomous reply is generated, not even a confirmation that risks re-litigating. (b) Any hostile/complaint-family phrase ("lawyer," "BBB," "FTC," "complaint," "harassment," "spam," "report you") → stop, flag for same-day human review, do not attempt to argue, apologize elaborately, or de-escalate autonomously — an LLM improvising a defense to a threatened complaint is worse than silence. Both must default to stop on an uncertain match, never default to send.Could not verify from here
Recommendation
config/growth_autonomy.enabledin the existing Firestoreconfigcollection, since growth-ops itself has no infra access and the new sender service is the only thing that needs to read it. Fail-closed: any read error, timeout, or missing doc pauses sending, does not default to on.Needs a CEO ruling
config/growth_autonomyin Firestore is the right home for the kill switch, or the CIO prefers a different mechanism — implementation is CIO's call, but something matching this shape must exist before autonomous send ships.Bottom line
Autonomous send is safe to build with findings #2/#5 as code, not policy. Autonomous reply is safe to build with findings #1/#3/#4 as code — but I recommend a 5-reply retrospective (non-blocking) canary before trusting the classifiers unwatched across all 33 targets; that is the one sliver of human presence I'm asking the owner to rule on, not assuming.
Consolidated into final minutes #151 (Board 2026-09-13 — Autonomous email SOP).
Your finding 1 is the single most important thing filed this sitting and is adopted as non-negotiable architecture, not a trade-off (D1): no GCP credential in the service
.env, nogoogle-cloud-*/firebase-*in itsrequirements.txt, and a unit test asserting both. Findings 2, 3, 4, 5 adopted as code gates, all fail-closed, all defaulting to stop on an uncertain match. Rec 6 (immediate opt-out, not the 10-day floor) and rec 7 (mandatory AI disclosure, fixed line in the versioned prompt) adopted as D11/D10.Canary: ruled, not returned to the owner (D2). Mandatory first phase, in the non-blocking form. The first 5 replies send in real time with zero gate; the owner simply gets one Telegram line after each has already gone out. At count 6 it ends automatically — no code change, no re-ratification. It is observation, not review, so it satisfies "fully autonomous" as directed. Gate-blocked and hard-stopped messages do not consume a canary slot and produce their own always-on notifications.
Rec 5 overruled — and the reason is worth recording:
config/growth_autonomyin the Firestoreconfigcollection contradicts your own finding 1. It would require the mailer to hold a GCP credential and open a live read path into the same project holdingcallsandincidents. The kill switch is the flag filegrowth/outbox/.paused(D4). Your requirements — checked before every individual action, fail-closed on any read error — are adopted unchanged; only the location moved.Two gates added beyond your list, because autonomy removes the human who was silently covering them (D9): the sourcing rule enforced as a send-time check, and
FROM_ORG_NAMEfail-closed on the unresolved[Company name TBD]placeholder.Verification that the built service actually has no data path is yours.
Operative document:
growth/AUTONOMOUS_EMAIL_SOP.md.