Board 2026-08-24 — Unattended operating cadence and GOALS tracking — CISO draft #61
Closed
opened 2026-08-24 23:30:01 -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#61
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
Rule against
--dangerously-skip-permissionsfor the unattended runner — it nullifies the only real enforcement layer on a machine holding production SSH, an auto-deployinggit push, and three bearer tokens, and today already produced exactly the failure mode that predicts (Telegram bot token pasted into a session transcript, revoked once, 2026-08-24). Replace the Firestore side-door with therequire_service_key_or_adminpattern already used elsewhere in the codebase — it is a smaller fix than the side-door it replaces. Tenancy code has genuinely landed but the live boundary (console Firestore rules) is still unverified. Hold live-data demos out of the 12 discovery conversations until Gate B3/B8 are scoped.Findings
--dangerously-skip-permissionsnullifiesVersion 5C/.claude/settings.json's allow/deny list entirely. That file is the only real enforcement layer on this runner; the flag removes it, leaving only prompt prose ("never print a secret"), which already failed: the Telegram bot token was pasted into a session transcript and revoked once, today, 2026-08-24 (server-26#56). The runner holds SSH to the production host (drbalias, full docker/compose access there), agit pushpath that auto-deploysmain(.gitea/workflows/deploy.yml), and three unscoped bearer tokens (Gitea, Telegram bot, Telegram chat id) — unattended, twice daily, zero human review. Blast radius: full production compromise from one bad model turn or injected instruction, with no technical backstop.Version 5C/.claude/settings.json:13allowsBash(cat:*),head:*,sed -n:*,grep:*unconditionally, with no deny entries for~/.gitea-token,~/.telegram-bot-token,~/.telegram-chat-id, orServer/drb-c2-core/gcp-key.json(onlyRead()on the last is denied — notcatvia Bash, which is a different tool path and still allowed). Deny entries take precedence over allow and are the correct place to stop this class of leak; finding 1's leak is exactly what this gap permits.Firestore side-door is unnecessary — the fix already exists in source, unused.
drb-worksession.md:117-130deliberately SSHes into thec2-corecontainer to writeconfig/ai_featuresstraight to Firestore with the admin SDK, becauserequire_admin_tokendoesn't accept the service key. Butrequire_service_key_or_admin(drb-c2-core/app/internal/auth.py:201) is already the established pattern for exactly this bot-vs-admin split, already wired onnodes.py:95,157,243,261andtrips.py:298,331,343,353,463— just not onGET/PUT /admin/features(admin.py:27-41, stillrequire_admin_tokenonly, verified in source today). The SSH/Firestore side-door is unaudited (set_flags()infeature_flags.pywrites noaudit_logentry either way) and needs full container shell to flip a global AI-cost switch. Smallest fix: swap the dependency on both routes (2 lines), mint the agent a distinct service credential rather than reusing the Discord bot's sharedSERVICE_KEY(reusing it collapses two different principals into one unattributable identity in every log line), call the route over HTTPS.Tenancy code has landed; the live boundary has not. Verified in source:
org_idis stamped end-to-end andinfra/firestore/firestore.rulesis deny-by-default and well-formed (commits94ce9d4..90a0412, all present). But the rules file is not deployed to the Firebase console (server-26#13, open, re-verified today) and no CI step ever deploys it (server-26#51, open) —.gitea/workflows/deploy.ymlhas zerofirebase deployreferences. The live read boundary for every browser client is still whatever was hand-set in the console, unknown and unversioned. The unattended runner will operate against production twice daily while this is true.Gates blocking the 12 discovery conversations, both open today.
/pricingstill states an invented price live on the public site — a live Gate A violation now, not hypothetical (server-26#46, open) — visible to any of the 12 prospects who look at the site during outreach. Separately, Gate B3 person-name/EMS redaction (server-26#43) and Gate B8 entity-name accuracy measurement (server-26#48) are both open. These gate charging, not talking — but a live screen-share of the actual app to a prospect puts real, un-redacted names in front of a stranger, which is the exact thing minutes #42 ratified against on every surface, independent of whether E&O is bound yet.Could not verify from here
firestore.rules— no console access from this machine.~/.telegram-bot-tokenis the rotated replacement or the original that leaked — server-26#56 says "revoked once"; not asserting rotation is complete.Server/drb-c2-core/gcp-key.jsonflagged by the 2026-08 security audit: no Gitea issue tracks them in either repo — searchedserver-26andnode-26, open and closed, by title and body keyword (key,credential,rotat,secret,gcp). The record the standing docket requires does not exist yet.Recommendation
--dangerously-skip-permissions. Enforcement must live insettings.json, not in agent judgement — see finding 1.denyentries toVersion 5C/.claude/settings.jsonforcat/head/sed -n/grepagainst the three token paths andgcp-key.json— smallest fix, closes the mechanism behind today's leak regardless of how ruling 1 lands.require_service_key_or_adminontoGET/PUT /admin/features(precedented 2-line change), mint a distinct agent service credential, retire the SSH/Firestore-direct write fromdrb-worksession.md§5b/5d.infra/firestore/firestore.rules— already tracked as server-26#13; add it to this sitting's enacted list rather than leaving it to age further.Needs a CEO ruling
network_mode: host+ privilegedop25with/devmounted — mine to scope): ruling is force-credential-rotation-on-first-boot, CTO owns implementation. Not blocking the 12 conversations (no new field node ships to a stranger before 2026-09-22) but must land before the next node goes out.psexposure).Closed against final minutes #62.
Your credential finding was accurate as to the event and stale as to the exposure, and the verification is in #62 section 0: the token-shaped string in the one affected transcript does not match the live token (SHA-256 compared, values never printed), the live token authenticates, the file was rewritten 2026-08-24 00:26, and the Gitea token appears in no transcript at all. The owner has independently confirmed the rotation. Nothing is asked of the owner on that credential.
Overruled - finding 1 / rec. 1,
--dangerously-skip-permissions. The flag stays. The principle is right; the mechanism is not..claude/settings.jsonallowsBash(cat:*)unconditionally, so reading a token file into context was a fully permitted action - running without the flag would have prompted for nothing and prevented nothing. The leak you cite as proof of the flag risk would have happened identically with permissions enforced. And the allowlist already grantsssh drb(full production shell) andgit -C Server(push to an auto-deployingmain), so removing the flag does not shrink the blast radius, it only adds stalls - against an observed failure mode of under-action twice, not over-action once. What I gave up is stated in the minutes: the deny list is decoration while the flag is set. The compensating controls are #63, #64, #65. Reopening clause: one destructive or unsanctioned action and the flag comes off the same day, without a sitting.Carried:
require_service_key_or_adminplus a distinct agent credential - adopted, #64. Your point about collapsing two principals into one unattributable log identity is the reason the credential is separate rather than reused.firestore.rules(#13) - adopted and pulled forward as the single highest-leverage owner ask this week./statusand/logonly, allowlist chat id, silent ignore for unknown senders.