Status: FINAL. Amends minutes #53 (cadence) and adds a checkpoint to minutes #54.
Drafts: #58 (COO) · #59 (CMO) · #60 (CTO) · #61 (CISO). All four closed against these minutes.
0. The credential item, first — CLOSED, not open
CISO (#61 finding 1) reported a Telegram bot token pasted into a session transcript and revoked once on 2026-08-24. The report is accurate as to the event and stale as to the exposure. Verified this sitting, without printing any value:
The token-shaped string present in exactly one session transcript does not match the token now in ~/.telegram-bot-token (SHA-256 comparison, values never printed). It is the revoked one.
The live token authenticates (getMe → ok=true, @discord_radio_bot_dev_bot) and the file was rewritten 2026-08-24 00:26, i.e. rotation completed the same day as the leak.
The Gitea token does not appear in any of the 12 transcripts. Neither does any other live credential.
The owner has independently confirmed the rotation and considers the exposure closed. No owner action is requested on this credential. It is recorded here as an incident that occurred and was remediated within hours.
Decision 0 — the control question stays open even though the exposure does not. "How did a token reach a transcript at all, and what stops the next one" is the live question. The answer is not a permission prompt (see Decision 1). It is that the runner must never hold a secret in its context. Every cat ~/.*-token in drb-worksession.md and the officer prompts gets replaced with a WSL helper that reads the secret internally and never echoes it. Owner: CTO. Due 2026-08-31.
Founding-agenda item 2 (credential rotation, due 2026-08-30) is not discharged by this: the 2026-08 security audit two API keys and gcp-key.json still have no tracking issue in either repo (#61, "could not verify"). CISO files that docket. The Telegram token is listed there as already closed.
1. --dangerously-skip-permissions — the flag STAYS. CISO overruled.
The CISO principle is right and its mechanism is wrong, and the mechanism is what I was asked to rule on.
Why the flag is not the control that failed.Version 5C/.claude/settings.json allows Bash(cat:*) unconditionally. Reading a token file into context was a fully permitted action. Running without the flag would have prompted for nothing and prevented nothing. The one demonstrated leak this project has had would have happened identically with permissions enforced.
Why removing it costs more than it buys. The allowlist already grants Bash(wsl -e bash -lc "ssh drb *) — full production shell — and Bash(git -C ".../Server":*), which includes git push to an auto-deploying main. Every capability CISO calls blast radius is explicitly allow-listed. Removing the flag does not shrink the blast radius; it only adds stalls.
And the observed failure mode is under-action, not over-action. The owner notes the two runs that fired earlier produced no work at all, and both repos went flat for a day-plus while the job ran read-only. A permission prompt in an unattended run does not fail safe — it fails silent, burns the cycle, and produces the exact outcome we are trying to stop. We have zero instances of the runner doing something destructive and two instances of it doing nothing.
What I am giving up by ruling this way: the deny list (docker, rm -rf, git push --force, git reset --hard) is decoration while the flag is set. I accept that, and I am replacing it with controls that do not depend on a dialog box:
Control
Owner
Due
a. No secret ever enters agent context — WSL wrapper scripts, no cat of a token anywhere in a prompt
CTO
2026-08-31
b. require_service_key_or_admin on /admin/features; distinct agent service credential (not the Discord bot shared SERVICE_KEY); retire the SSH/Firestore side-door
CTO
2026-08-31
c. Once (b) lands, ssh drb comes out of the AI-flag path in drb-worksession.md
CTO
2026-08-31
d. Deploy rollback (Decision 3) before any unattended push to the correlator/AI/upload files
CTO
2026-08-31
CISO rec. 2 (deny entries for token paths) is adopted anyway — it costs nothing and it is correct for any future attended session, where the flag is not set. It is a speed bump, not the boundary, and must not be described as one.
Reopening clause: if the runner takes a single destructive or unsanctioned action, the flag comes off the same day without a sitting.
2. /admin/features Firestore side-door — CTO and CISO agree; ADOPTED as written
Both drafts independently reached the same two-line fix and named the same precedent. No conflict to resolve. Move GET/PUT /admin/features from require_admin_token to require_service_key_or_admin (drb-c2-core/app/internal/auth.py:201, already used on nodes.py and trips.py), mint the agent a distinct service credential so the audit log can tell the agent from the Discord bot, retire the container-shell Firestore write from drb-worksession.md. Fold in CTO rec. 2: one helper that always sets config/ai_featuresand both systems ai_flags, so ON cannot half-apply the way OFF already cannot. Owner: CTO. Due 2026-08-31.
3. Deploy rollback — the runner may push, but not everywhere
CTO finding 3 is correct: .gitea/workflows/deploy.yml:120 runs compose up -d before the health check, notify-failure only posts to Discord, and its "production is still running the previous build" text is false in the healthy-but-broken case.
Blocking all autonomous pushes until that is fixed re-creates the failure that already cost a day. So, split by blast radius:
The runner may push to main autonomously, unchanged, for everything else.
The runner may NOT push, unattended, any change touching incident_correlator.py, llm_correlator.py, intelligence.py, or routers/upload.py until the rollback path exists. Those are the files where a green /health and a correct git_sha coexist with silently corrupted incidents for 12 hours. That work gets staged on a branch and reported, not pushed.
CTO rec. 5 (tail c2-core logs ~10 min after a pipeline-touching deploy, git revert and push on a clear exception spike) is authorised and becomes the interim mechanism.
Owner: CTO. Rollback issue due 2026-08-31; the file restriction is in force from tonight.
4. The Monday board sitting moves into the runner — COO rec. 2 / CTO rec. 6 ADOPTED
Minutes #53 declined a daemon because "a cron job dies with its session and would silently stop." Task Scheduler survives reboots and reports over Telegram, so the premise is void — and the status quo #53 left in place produced the very outcome it feared, by neglect instead of by death.
From the 2026-08-31 run: on a Monday, the runner invokes the board skill before STEP 6 and files the four minutes:draft issues plus a CEO minutes:final.
Auto-finalisation is limited. Administrative and mechanical rulings — cadence, role scope, issue hygiene, the class #53 itself was — may self-finalise. Anything touching product scope, money, security posture, or market positioning stays minutes:draft until the owner or an attended sitting promotes it. A minutes:draft that sits unpromoted for two sittings gets escalated in the Telegram brief, not quietly ratified.
Containment may proceed autonomously and immediately; silence may not. Any credential revocation, rotation, or suspected exposure triggers an individually-sent NEEDS OWNER Telegram message in the same run — not a line buried in an issue body, which is how today incident actually surfaced. Owner: CTO, encoded into drb-worksession.md STEP 7 before 2026-08-31.
6. GOALS.md tracking — we are NOT on track, and there was no instrument to say so
29 days to 2026-09-22. Zero of the 12 discovery conversations are evidenced, and a search of server-26 open and closed returns no tracker for the thing minutes #54 called "the highest-value action in the company, above any code change." A ratified kill criterion with no instrument is the worst drift found this sitting — worse than any code finding in the four drafts.
Decision 6a — file the tracker. One server-26 issue, owner = the human owner, due 2026-09-22, one checkbox per conversation, updated by comment. Every future sitting reports a number, not an inference.
Decision 6b — the CMO 2026-09-05 checkpoint is RATIFIED (#59 rec. 6). If the count is still 0 on 2026-09-05, that is itself the signal, and it triggers the "beachhead dead" sitting minutes #54 already defines — we do not spend the remaining 17 days waiting out a test that never started. This amends minutes #54 and is stamped into GOALS.md.
Decision 6c — CMO rec. 4 ADOPTED as this week owner deliverable. CMO drafts the ~40-operator Westchester walk-in list (name, phone, address, from public listings, never sent anywhere) plus the one-line opener. The owner walks in. That is the owner-hour spend and it is named plainly, not dressed up as automatable. Target: 4 conversations by 2026-09-05.
Decision 6d — no live-data demo. The CISO position is UPHELD. No screen-share of the real app to a prospect until Gate B3 (#43, person-name/EMS redaction) is scoped. Minutes #42 ratified name suppression on every surface; a stranger watching the owner screen is a surface. Use a static screenshot with names removed, or describe it. This costs demo punch in the discovery conversations. I accept that — an un-redacted name in front of a stranger before E&O is bound is the one mistake that ends the commercial track outright.
7. Gate A / Gate B status, and what I enacted
Gate A was in live breach for a full day after ratification.https://drb.cusano.net/pricing returned 200 with the invented $0/$79/Custom catalog, SSO/SAML and uptime-SLA entitlement claims, and a disclaimer footnote — the exact "false price anchor with a footnote" #42 ruled worse than no price. CMO flagged it as the single most dangerous live claim on the site and was right.
Enacted this session, pushed as a1bdccf:
/pricing rewritten — no numbers, no plan cards, no interval toggle. "Pricing is in development", CTA to the existing/waitlist request-access page.
Homepage pricing teaser removed; PLANS import gone from app/page.tsx.
Homepage CTAs pointed at /login, which has no signup path — a real visitor could not create an account (CMO claims-audit row 2). Now /waitlist "Request access"; secondary CTA honestly labelled "Sign in".
lib/billing.ts: the uncommitted local guardrail comment — a Gate A control sitting untracked in a working tree — is now committed, so the next person to import PLANS is warned at the definition site.
npx tsc --noEmit clean.
/settings/billing is unchanged and still stubbed. It is authenticated, not a public price surface; it stays with #46, which remains open until the entitlement copy there is reconciled.
Gate B: #13 is the load-bearing blocker and it is minutes of owner time. CTO rec. 10 and CISO finding 4 converge: infra/firestore/firestore.rules is deny-by-default, well-formed, committed — and never deployed. The live read boundary for every browser client is whatever was hand-set in the console, unknown and unversioned, while the frontend reads Firestore directly. This is pulled forward as the single highest-leverage owner ask this week, ahead of everything except the conversations:
Owner: the human owner. Due 2026-08-31. Roughly five minutes. #51 (CI step so it can never drift again) follows and is engineering work, not owner work.
8. board:agenda items — all three scoped, label removed
server-26#56 (Telegram control plane) — SCOPE DOWN, build the slice. COO rec. 4 and the CMO ruling request agree; CTO wanted design-only. I side with COO/CMO because the two pieces that earn their place are the two that answer this agenda: a read-only /status command (directly answers "the runs produced no output") and /log <note> feeding the Decision 6a conversation counter. Hard requirement: allowlist chat id 5028509822, silently ignore every other sender — no reply confirms the bot is live. Everything state-changing (/cto, /ciso, /board, anything spending money) is deferred to a CTO-scoped sitting. Answering its own question 1: yes, it earns its place, at this size only. Owner: CTO, sign-off CISO, by 2026-08-31.
node-26#1 (node-002 first-boot default credentials) — P0, ahead of Gate A/B backlog. COO and CTO both refused to defer this and CISO named the fix. A default-credential dashboard on a node running network_mode: host beside a privileged op25 with /dev mounted is host-level exposure on hardware already in friends-and-family hands. Ruling: force credential rotation on first boot. Owner: CTO. It becomes the next single engineering issue for the runner. If it cannot be fixed over MQTT/WireGuard, say so explicitly and log a physical-visit date — it does not get silently reclassified as a normal code fix.
node-26#4 (one-line install needs a manual git clone) — DEFERRED, with a reason. CTO rec. 8 is right: Gate A blocks publishing a price, so there is no self-serve customer to onboard. Building install automation now is ahead of the funnel. Revisit at the first signed customer. If it ever proceeds, the CISO condition binds: the enrollment token must never appear as a plaintext CLI argument (shell history, ps).
#57 recurring correlation dump covers #5 and #35 only. It structurally cannot answer #27 (needs the call-end-to-incident-created timestamp delta, not orphan totals) or #28 (needs the one-time backfill route in DEFERRED.md:51 — a passive scan cannot surface a document nothing links to). Running it every cycle and calling those covered is ceremony that reads as diligence. #27 and #28 get comments recording this; neither is folded into #57.
#45 (7 consecutive days of real AI cost against a provider invoice) has no collection mechanism — the runbook only opens the AI window when a correlation-affecting commit is live, so #45 can stall forever at zero qualifying commits. CTO proposes one explicit contiguous 7-day window with a stated dollar cap; the cap figure is owner-only money and is not being invented here. CTO comments the proposed figure on #45; owner confirms by reply.
10. Owner-hour budget — under the 5h/week hard cap
Total ≈ 3h40m. Under cap. Nothing else is asked of the owner this week, and every engineering decision above was deliberately assigned to an agent or the CTO for that reason.
Follow-up issues filed from these minutes
See the linked issues in the comment below. Existing issues touched: #46 (Gate A, partly enacted by a1bdccf, stays open for /settings/billing), #13 (pulled forward), #56 (scoped down), #43, #48, #27, #28, #45, #51, node-26#1 (P0), node-26#4 (deferred).
Document amendments enacted
GOALS.md — 2026-09-05 checkpoint stamped in (Decision 6b).
BUSINESS_MODEL.md — Gate A recorded as enforced on the public site by a1bdccf.
.claude/skills/board/SKILL.md — cadence item struck from the founding agenda; Monday sitting now delivered by the runner.
CLAUDE.md — cadence and ratification status updated.
Runner authorisation + credential-escalation rules into drb-worksession.md
CTO
2026-08-31
Enacted in code this session: a1bdccf (Gate A - prices off every public surface, CTAs to /waitlist, billing.ts guardrail committed, tsc --noEmit clean).
# Board minutes — 2026-08-24 — Unattended operating cadence and GOALS tracking
**Status: FINAL.** Amends minutes #53 (cadence) and adds a checkpoint to minutes #54.
Drafts: #58 (COO) · #59 (CMO) · #60 (CTO) · #61 (CISO). All four closed against these minutes.
---
## 0. The credential item, first — CLOSED, not open
CISO (#61 finding 1) reported a Telegram bot token pasted into a session transcript and revoked once on 2026-08-24. **The report is accurate as to the event and stale as to the exposure.** Verified this sitting, without printing any value:
- The token-shaped string present in exactly one session transcript **does not match** the token now in `~/.telegram-bot-token` (SHA-256 comparison, values never printed). It is the revoked one.
- The live token authenticates (`getMe` → `ok=true`, `@discord_radio_bot_dev_bot`) and the file was rewritten **2026-08-24 00:26**, i.e. rotation completed the same day as the leak.
- The **Gitea token does not appear in any of the 12 transcripts.** Neither does any other live credential.
**The owner has independently confirmed the rotation and considers the exposure closed.** No owner action is requested on this credential. It is recorded here as an incident that occurred and was remediated within hours.
**Decision 0 — the control question stays open even though the exposure does not.** "How did a token reach a transcript at all, and what stops the next one" is the live question. The answer is *not* a permission prompt (see Decision 1). It is that **the runner must never hold a secret in its context**. Every `cat ~/.*-token` in `drb-worksession.md` and the officer prompts gets replaced with a WSL helper that reads the secret internally and never echoes it. Owner: **CTO**. Due **2026-08-31**.
Founding-agenda item 2 (credential rotation, due 2026-08-30) is **not** discharged by this: the 2026-08 security audit two API keys and `gcp-key.json` still have no tracking issue in either repo (#61, "could not verify"). CISO files that docket. The Telegram token is listed there as already closed.
---
## 1. `--dangerously-skip-permissions` — the flag STAYS. CISO overruled.
The CISO principle is right and its mechanism is wrong, and the mechanism is what I was asked to rule on.
**Why the flag is not the control that failed.** `Version 5C/.claude/settings.json` allows `Bash(cat:*)` unconditionally. Reading a token file into context was a **fully permitted action**. Running without the flag would have prompted for nothing and prevented nothing. The one demonstrated leak this project has had would have happened identically with permissions enforced.
**Why removing it costs more than it buys.** The allowlist already grants `Bash(wsl -e bash -lc "ssh drb *)` — full production shell — and `Bash(git -C ".../Server":*)`, which includes `git push` to an auto-deploying `main`. Every capability CISO calls blast radius is *explicitly allow-listed*. Removing the flag does not shrink the blast radius; it only adds stalls.
**And the observed failure mode is under-action, not over-action.** The owner notes the two runs that fired earlier produced no work at all, and both repos went flat for a day-plus while the job ran read-only. A permission prompt in an unattended run does not fail safe — it fails *silent*, burns the cycle, and produces the exact outcome we are trying to stop. We have zero instances of the runner doing something destructive and two instances of it doing nothing.
**What I am giving up by ruling this way:** the deny list (`docker`, `rm -rf`, `git push --force`, `git reset --hard`) is decoration while the flag is set. I accept that, and I am replacing it with controls that do not depend on a dialog box:
| Control | Owner | Due |
|---|---|---|
| a. No secret ever enters agent context — WSL wrapper scripts, no `cat` of a token anywhere in a prompt | CTO | 2026-08-31 |
| b. `require_service_key_or_admin` on `/admin/features`; distinct agent service credential (**not** the Discord bot shared `SERVICE_KEY`); retire the SSH/Firestore side-door | CTO | 2026-08-31 |
| c. Once (b) lands, `ssh drb` comes out of the AI-flag path in `drb-worksession.md` | CTO | 2026-08-31 |
| d. Deploy rollback (Decision 3) before any unattended push to the correlator/AI/upload files | CTO | 2026-08-31 |
CISO rec. 2 (deny entries for token paths) is **adopted anyway** — it costs nothing and it is correct for any future attended session, where the flag is not set. It is a speed bump, not the boundary, and must not be described as one.
**Reopening clause:** if the runner takes a single destructive or unsanctioned action, the flag comes off the same day without a sitting.
---
## 2. `/admin/features` Firestore side-door — CTO and CISO agree; ADOPTED as written
Both drafts independently reached the same two-line fix and named the same precedent. No conflict to resolve. Move `GET`/`PUT /admin/features` from `require_admin_token` to `require_service_key_or_admin` (`drb-c2-core/app/internal/auth.py:201`, already used on `nodes.py` and `trips.py`), mint the agent a **distinct** service credential so the audit log can tell the agent from the Discord bot, retire the container-shell Firestore write from `drb-worksession.md`. Fold in CTO rec. 2: one helper that always sets `config/ai_features` **and** both systems `ai_flags`, so ON cannot half-apply the way OFF already cannot. Owner: **CTO**. Due **2026-08-31**.
## 3. Deploy rollback — the runner may push, but not everywhere
CTO finding 3 is correct: `.gitea/workflows/deploy.yml:120` runs `compose up -d` before the health check, `notify-failure` only posts to Discord, and its "production is still running the previous build" text is **false** in the healthy-but-broken case.
Blocking all autonomous pushes until that is fixed re-creates the failure that already cost a day. So, split by blast radius:
- **The runner may push to `main` autonomously**, unchanged, for everything else.
- **The runner may NOT push, unattended, any change touching `incident_correlator.py`, `llm_correlator.py`, `intelligence.py`, or `routers/upload.py`** until the rollback path exists. Those are the files where a green `/health` and a correct `git_sha` coexist with silently corrupted incidents for 12 hours. That work gets staged on a branch and reported, not pushed.
- CTO rec. 5 (tail `c2-core` logs ~10 min after a pipeline-touching deploy, `git revert` and push on a clear exception spike) is **authorised** and becomes the interim mechanism.
Owner: **CTO**. Rollback issue due **2026-08-31**; the file restriction is in force from tonight.
## 4. The Monday board sitting moves into the runner — COO rec. 2 / CTO rec. 6 ADOPTED
Minutes #53 declined a daemon because "a cron job dies with its session and would silently stop." Task Scheduler survives reboots and reports over Telegram, so the premise is void — and the status quo #53 left in place produced the very outcome it feared, by neglect instead of by death.
From the **2026-08-31** run: on a Monday, the runner invokes the `board` skill before STEP 6 and files the four `minutes:draft` issues plus a CEO `minutes:final`.
**Auto-finalisation is limited.** Administrative and mechanical rulings — cadence, role scope, issue hygiene, the class #53 itself was — may self-finalise. **Anything touching product scope, money, security posture, or market positioning stays `minutes:draft` until the owner or an attended sitting promotes it.** A `minutes:draft` that sits unpromoted for two sittings gets escalated in the Telegram brief, not quietly ratified.
## 5. Credential/containment escalation rule — COO rec. 1(b) ADOPTED
Containment may proceed autonomously and immediately; **silence may not**. Any credential revocation, rotation, or suspected exposure triggers an individually-sent `NEEDS OWNER` Telegram message in the same run — not a line buried in an issue body, which is how today incident actually surfaced. Owner: **CTO**, encoded into `drb-worksession.md` STEP 7 before **2026-08-31**.
## 6. GOALS.md tracking — we are NOT on track, and there was no instrument to say so
29 days to 2026-09-22. **Zero of the 12 discovery conversations are evidenced**, and a search of `server-26` open and closed returns no tracker for the thing minutes #54 called "the highest-value action in the company, above any code change." A ratified kill criterion with no instrument is the worst drift found this sitting — worse than any code finding in the four drafts.
- **Decision 6a — file the tracker.** One `server-26` issue, owner = **the human owner**, due **2026-09-22**, one checkbox per conversation, updated by comment. Every future sitting reports a number, not an inference.
- **Decision 6b — the CMO 2026-09-05 checkpoint is RATIFIED** (#59 rec. 6). If the count is still **0 on 2026-09-05**, that is itself the signal, and it triggers the "beachhead dead" sitting minutes #54 already defines — we do not spend the remaining 17 days waiting out a test that never started. This amends minutes #54 and is stamped into `GOALS.md`.
- **Decision 6c — CMO rec. 4 ADOPTED as this week owner deliverable.** CMO drafts the ~40-operator Westchester walk-in list (name, phone, address, from public listings, **never sent anywhere**) plus the one-line opener. The owner walks in. That is the owner-hour spend and it is named plainly, not dressed up as automatable. Target: **4 conversations by 2026-09-05.**
- **Decision 6d — no live-data demo. The CISO position is UPHELD.** No screen-share of the real app to a prospect until Gate B3 (#43, person-name/EMS redaction) is scoped. Minutes #42 ratified name suppression **on every surface**; a stranger watching the owner screen is a surface. Use a static screenshot with names removed, or describe it. This costs demo punch in the discovery conversations. I accept that — an un-redacted name in front of a stranger before E&O is bound is the one mistake that ends the commercial track outright.
## 7. Gate A / Gate B status, and what I enacted
**Gate A was in live breach for a full day after ratification.** `https://drb.cusano.net/pricing` returned 200 with the invented `$0/$79/Custom` catalog, SSO/SAML and uptime-SLA entitlement claims, and a disclaimer footnote — the exact "false price anchor with a footnote" #42 ruled worse than no price. CMO flagged it as the single most dangerous live claim on the site and was right.
**Enacted this session, pushed as `a1bdccf`:**
- `/pricing` rewritten — no numbers, no plan cards, no interval toggle. "Pricing is in development", CTA to the **existing** `/waitlist` request-access page.
- Homepage pricing teaser removed; `PLANS` import gone from `app/page.tsx`.
- Homepage CTAs pointed at `/login`, which has **no signup path** — a real visitor could not create an account (CMO claims-audit row 2). Now `/waitlist` "Request access"; secondary CTA honestly labelled "Sign in".
- `lib/billing.ts`: the uncommitted local guardrail comment — a Gate A control sitting untracked in a working tree — is now **committed**, so the next person to import `PLANS` is warned at the definition site.
- `npx tsc --noEmit` clean.
`/settings/billing` is unchanged and still stubbed. It is authenticated, not a public price surface; it stays with **#46**, which remains open until the entitlement copy there is reconciled.
**Gate B: #13 is the load-bearing blocker and it is minutes of owner time.** CTO rec. 10 and CISO finding 4 converge: `infra/firestore/firestore.rules` is deny-by-default, well-formed, committed — and never deployed. The live read boundary for every browser client is whatever was hand-set in the console, unknown and unversioned, while the frontend reads Firestore directly. **This is pulled forward as the single highest-leverage owner ask this week**, ahead of everything except the conversations:
```
firebase deploy --only firestore:rules,firestore:indexes --project discord-radio-bot-461301
```
Owner: **the human owner**. Due **2026-08-31**. Roughly five minutes. #51 (CI step so it can never drift again) follows and is engineering work, not owner work.
## 8. `board:agenda` items — all three scoped, label removed
- **server-26#56 (Telegram control plane) — SCOPE DOWN, build the slice.** COO rec. 4 and the CMO ruling request agree; CTO wanted design-only. I side with COO/CMO because the two pieces that earn their place are the two that answer *this* agenda: a **read-only `/status`** command (directly answers "the runs produced no output") and **`/log <note>`** feeding the Decision 6a conversation counter. Hard requirement: allowlist chat id `5028509822`, silently ignore every other sender — no reply confirms the bot is live. Everything state-changing (`/cto`, `/ciso`, `/board`, anything spending money) is **deferred** to a CTO-scoped sitting. Answering its own question 1: yes, it earns its place, at this size only. Owner: **CTO**, sign-off **CISO**, by **2026-08-31**.
- **node-26#1 (node-002 first-boot default credentials) — P0, ahead of Gate A/B backlog.** COO and CTO both refused to defer this and CISO named the fix. A default-credential dashboard on a node running `network_mode: host` beside a privileged `op25` with `/dev` mounted is host-level exposure on hardware already in friends-and-family hands. Ruling: **force credential rotation on first boot**. Owner: **CTO**. It becomes the next single engineering issue for the runner. If it cannot be fixed over MQTT/WireGuard, say so explicitly and log a physical-visit date — it does not get silently reclassified as a normal code fix.
- **node-26#4 (one-line install needs a manual git clone) — DEFERRED, with a reason.** CTO rec. 8 is right: Gate A blocks publishing a price, so there is no self-serve customer to onboard. Building install automation now is ahead of the funnel. Revisit at the **first signed customer**. If it ever proceeds, the CISO condition binds: the enrollment token must never appear as a plaintext CLI argument (shell history, `ps`).
## 9. Instrumentation honesty — CTO finding 4 ADOPTED
#57 recurring correlation dump covers **#5** and **#35** only. It structurally cannot answer **#27** (needs the call-end-to-incident-created timestamp delta, not orphan totals) or **#28** (needs the one-time backfill route in `DEFERRED.md:51` — a passive scan cannot surface a document nothing links to). Running it every cycle and calling those covered is ceremony that reads as diligence. #27 and #28 get comments recording this; neither is folded into #57.
**#45** (7 consecutive days of real AI cost against a provider invoice) has no collection mechanism — the runbook only opens the AI window when a correlation-affecting commit is live, so #45 can stall forever at zero qualifying commits. CTO proposes one explicit contiguous 7-day window with a stated dollar cap; **the cap figure is owner-only money** and is not being invented here. CTO comments the proposed figure on #45; owner confirms by reply.
## 10. Owner-hour budget — under the 5h/week hard cap
| Owner item | Time |
|---|---|
| `firebase deploy` firestore rules (#13) | ~5 min |
| Walk-in conversations, target 4 by 2026-09-05 | ~3 h |
| Confirm the 2 outstanding API keys + `gcp-key.json` rotation (exempt per #54 decision 8) | ~30 min |
| Reply with the #45 dollar cap | ~2 min |
Total ≈ **3h40m**. Under cap. Nothing else is asked of the owner this week, and every engineering decision above was deliberately assigned to an agent or the CTO for that reason.
---
## Follow-up issues filed from these minutes
See the linked issues in the comment below. Existing issues touched: **#46** (Gate A, partly enacted by `a1bdccf`, stays open for `/settings/billing`), **#13** (pulled forward), **#56** (scoped down), **#43**, **#48**, **#27**, **#28**, **#45**, **#51**, **node-26#1** (P0), **node-26#4** (deferred).
## Document amendments enacted
- `GOALS.md` — 2026-09-05 checkpoint stamped in (Decision 6b).
- `BUSINESS_MODEL.md` — Gate A recorded as enforced on the public site by `a1bdccf`.
- `.claude/skills/board/SKILL.md` — cadence item struck from the founding agenda; Monday sitting now delivered by the runner.
- `CLAUDE.md` — cadence and ratification status updated.
---
## Follow-up issues filed (all live)
| # | Work | Owner | Due |
|---|---|---|---|
| #63 | Remove secrets from agent context - WSL credential wrappers, plus deny entries | CTO | 2026-08-31 |
| #64 | `require_service_key_or_admin` on `/admin/features`, distinct agent credential, single AI-on helper | CTO | 2026-08-31 |
| #65 | Deploy rollback: health-gate `compose up -d`, auto-revert, fix the false notify-failure text | CTO | 2026-08-31 |
| #66 | TRACKER: 12 discovery conversations, checkpoint 2026-09-05 | owner | 2026-09-22 |
| #67 | Credential rotation docket: 2 API keys + `gcp-key.json` | owner | 2026-08-30 |
| #68 | Runner authorisation + credential-escalation rules into `drb-worksession.md` | CTO | 2026-08-31 |
Enacted in code this session: **`a1bdccf`** (Gate A - prices off every public surface, CTAs to `/waitlist`, `billing.ts` guardrail committed, `tsc --noEmit` clean).
Owner ruling 2026-08-26: one run per day, not two. This supersedes the twice-daily cadence in board minutes #62 (Decision 4's Monday board sitting is unaffected — it rides on whichever run falls on a Monday).
Revised command — keep DRB Session AM at 02:37, retire DRB Session PM:
Disable- rather than Unregister- so the cadence can be reversed without rebuilding the task.
drb-worksession.md now carries the cadence at the top of the file: there is no second bite at the day, so a run that lands nothing costs the company a full day. One engineering item and one business item, finished, beats three started.
Note this raises the stakes on the supervisor in this issue: with two runs a day a silent failure cost half a day, with one it costs all of it.
**Owner ruling 2026-08-26: one run per day, not two.** This supersedes the twice-daily cadence in board minutes #62 (Decision 4's Monday board sitting is unaffected — it rides on whichever run falls on a Monday).
Revised command — keep `DRB Session AM` at 02:37, retire `DRB Session PM`:
```powershell
$p = 'H:\Cusano-Document-Storage\Logan\Projects\Discord Radio Bot Project\Version 5C\.claude\scheduled\run-session.ps1'
$a = New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$p`" -Runner run-worksession.cmd -Label ws"
Set-ScheduledTask 'DRB Session AM' -Action $a -Trigger (New-ScheduledTaskTrigger -Daily -At 02:37)
Disable-ScheduledTask 'DRB Session PM'
```
`Disable-` rather than `Unregister-` so the cadence can be reversed without rebuilding the task.
`drb-worksession.md` now carries the cadence at the top of the file: there is no second bite at the day, so a run that lands nothing costs the company a full day. One engineering item and one business item, finished, beats three started.
Note this raises the stakes on the supervisor in this issue: with two runs a day a silent failure cost half a day, with one it costs all of it.
Closing per #146 D8 (2026-09-13): a minutes:final issue is not a tracker. The record of a ratified decision is the stamp on the document; live work is tracked by its own work issue. Six minutes:final issues had been open 8-21 days with unexecuted decisions inside them and nobody looking.
Superseded by #146. Decision 6b's 2026-09-05 checkpoint auto-trigger did not fire — that failure is itself finding 1 behind #146 D3. The beachhead test's plan of record is replaced by #146 D1/D2: the hypothesis is not dead, the owner-cold-call delivery mechanism is, and a 2026-09-16 gate with an explicit default now governs. Decisions 6c/6d survive unchanged.
Closing per **#146 D8** (2026-09-13): *a `minutes:final` issue is not a tracker.* The record of a ratified decision is the stamp on the document; live work is tracked by its own work issue. Six minutes:final issues had been open 8-21 days with unexecuted decisions inside them and nobody looking.
**Superseded by #146.** Decision 6b's 2026-09-05 checkpoint auto-trigger did not fire — that failure is itself finding 1 behind **#146 D3**. The beachhead test's plan of record is replaced by **#146 D1/D2**: the hypothesis is not dead, the owner-cold-call delivery mechanism is, and a 2026-09-16 gate with an explicit default now governs. Decisions 6c/6d survive unchanged.
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.
Board minutes — 2026-08-24 — Unattended operating cadence and GOALS tracking
Status: FINAL. Amends minutes #53 (cadence) and adds a checkpoint to minutes #54.
Drafts: #58 (COO) · #59 (CMO) · #60 (CTO) · #61 (CISO). All four closed against these minutes.
0. The credential item, first — CLOSED, not open
CISO (#61 finding 1) reported a Telegram bot token pasted into a session transcript and revoked once on 2026-08-24. The report is accurate as to the event and stale as to the exposure. Verified this sitting, without printing any value:
~/.telegram-bot-token(SHA-256 comparison, values never printed). It is the revoked one.getMe→ok=true,@discord_radio_bot_dev_bot) and the file was rewritten 2026-08-24 00:26, i.e. rotation completed the same day as the leak.The owner has independently confirmed the rotation and considers the exposure closed. No owner action is requested on this credential. It is recorded here as an incident that occurred and was remediated within hours.
Decision 0 — the control question stays open even though the exposure does not. "How did a token reach a transcript at all, and what stops the next one" is the live question. The answer is not a permission prompt (see Decision 1). It is that the runner must never hold a secret in its context. Every
cat ~/.*-tokenindrb-worksession.mdand the officer prompts gets replaced with a WSL helper that reads the secret internally and never echoes it. Owner: CTO. Due 2026-08-31.Founding-agenda item 2 (credential rotation, due 2026-08-30) is not discharged by this: the 2026-08 security audit two API keys and
gcp-key.jsonstill have no tracking issue in either repo (#61, "could not verify"). CISO files that docket. The Telegram token is listed there as already closed.1.
--dangerously-skip-permissions— the flag STAYS. CISO overruled.The CISO principle is right and its mechanism is wrong, and the mechanism is what I was asked to rule on.
Why the flag is not the control that failed.
Version 5C/.claude/settings.jsonallowsBash(cat:*)unconditionally. Reading a token file into context was a fully permitted action. Running without the flag would have prompted for nothing and prevented nothing. The one demonstrated leak this project has had would have happened identically with permissions enforced.Why removing it costs more than it buys. The allowlist already grants
Bash(wsl -e bash -lc "ssh drb *)— full production shell — andBash(git -C ".../Server":*), which includesgit pushto an auto-deployingmain. Every capability CISO calls blast radius is explicitly allow-listed. Removing the flag does not shrink the blast radius; it only adds stalls.And the observed failure mode is under-action, not over-action. The owner notes the two runs that fired earlier produced no work at all, and both repos went flat for a day-plus while the job ran read-only. A permission prompt in an unattended run does not fail safe — it fails silent, burns the cycle, and produces the exact outcome we are trying to stop. We have zero instances of the runner doing something destructive and two instances of it doing nothing.
What I am giving up by ruling this way: the deny list (
docker,rm -rf,git push --force,git reset --hard) is decoration while the flag is set. I accept that, and I am replacing it with controls that do not depend on a dialog box:catof a token anywhere in a promptrequire_service_key_or_adminon/admin/features; distinct agent service credential (not the Discord bot sharedSERVICE_KEY); retire the SSH/Firestore side-doorssh drbcomes out of the AI-flag path indrb-worksession.mdCISO rec. 2 (deny entries for token paths) is adopted anyway — it costs nothing and it is correct for any future attended session, where the flag is not set. It is a speed bump, not the boundary, and must not be described as one.
Reopening clause: if the runner takes a single destructive or unsanctioned action, the flag comes off the same day without a sitting.
2.
/admin/featuresFirestore side-door — CTO and CISO agree; ADOPTED as writtenBoth drafts independently reached the same two-line fix and named the same precedent. No conflict to resolve. Move
GET/PUT /admin/featuresfromrequire_admin_tokentorequire_service_key_or_admin(drb-c2-core/app/internal/auth.py:201, already used onnodes.pyandtrips.py), mint the agent a distinct service credential so the audit log can tell the agent from the Discord bot, retire the container-shell Firestore write fromdrb-worksession.md. Fold in CTO rec. 2: one helper that always setsconfig/ai_featuresand both systemsai_flags, so ON cannot half-apply the way OFF already cannot. Owner: CTO. Due 2026-08-31.3. Deploy rollback — the runner may push, but not everywhere
CTO finding 3 is correct:
.gitea/workflows/deploy.yml:120runscompose up -dbefore the health check,notify-failureonly posts to Discord, and its "production is still running the previous build" text is false in the healthy-but-broken case.Blocking all autonomous pushes until that is fixed re-creates the failure that already cost a day. So, split by blast radius:
mainautonomously, unchanged, for everything else.incident_correlator.py,llm_correlator.py,intelligence.py, orrouters/upload.pyuntil the rollback path exists. Those are the files where a green/healthand a correctgit_shacoexist with silently corrupted incidents for 12 hours. That work gets staged on a branch and reported, not pushed.c2-corelogs ~10 min after a pipeline-touching deploy,git revertand push on a clear exception spike) is authorised and becomes the interim mechanism.Owner: CTO. Rollback issue due 2026-08-31; the file restriction is in force from tonight.
4. The Monday board sitting moves into the runner — COO rec. 2 / CTO rec. 6 ADOPTED
Minutes #53 declined a daemon because "a cron job dies with its session and would silently stop." Task Scheduler survives reboots and reports over Telegram, so the premise is void — and the status quo #53 left in place produced the very outcome it feared, by neglect instead of by death.
From the 2026-08-31 run: on a Monday, the runner invokes the
boardskill before STEP 6 and files the fourminutes:draftissues plus a CEOminutes:final.Auto-finalisation is limited. Administrative and mechanical rulings — cadence, role scope, issue hygiene, the class #53 itself was — may self-finalise. Anything touching product scope, money, security posture, or market positioning stays
minutes:draftuntil the owner or an attended sitting promotes it. Aminutes:draftthat sits unpromoted for two sittings gets escalated in the Telegram brief, not quietly ratified.5. Credential/containment escalation rule — COO rec. 1(b) ADOPTED
Containment may proceed autonomously and immediately; silence may not. Any credential revocation, rotation, or suspected exposure triggers an individually-sent
NEEDS OWNERTelegram message in the same run — not a line buried in an issue body, which is how today incident actually surfaced. Owner: CTO, encoded intodrb-worksession.mdSTEP 7 before 2026-08-31.6. GOALS.md tracking — we are NOT on track, and there was no instrument to say so
29 days to 2026-09-22. Zero of the 12 discovery conversations are evidenced, and a search of
server-26open and closed returns no tracker for the thing minutes #54 called "the highest-value action in the company, above any code change." A ratified kill criterion with no instrument is the worst drift found this sitting — worse than any code finding in the four drafts.server-26issue, owner = the human owner, due 2026-09-22, one checkbox per conversation, updated by comment. Every future sitting reports a number, not an inference.GOALS.md.7. Gate A / Gate B status, and what I enacted
Gate A was in live breach for a full day after ratification.
https://drb.cusano.net/pricingreturned 200 with the invented$0/$79/Customcatalog, SSO/SAML and uptime-SLA entitlement claims, and a disclaimer footnote — the exact "false price anchor with a footnote" #42 ruled worse than no price. CMO flagged it as the single most dangerous live claim on the site and was right.Enacted this session, pushed as
a1bdccf:/pricingrewritten — no numbers, no plan cards, no interval toggle. "Pricing is in development", CTA to the existing/waitlistrequest-access page.PLANSimport gone fromapp/page.tsx./login, which has no signup path — a real visitor could not create an account (CMO claims-audit row 2). Now/waitlist"Request access"; secondary CTA honestly labelled "Sign in".lib/billing.ts: the uncommitted local guardrail comment — a Gate A control sitting untracked in a working tree — is now committed, so the next person to importPLANSis warned at the definition site.npx tsc --noEmitclean./settings/billingis unchanged and still stubbed. It is authenticated, not a public price surface; it stays with #46, which remains open until the entitlement copy there is reconciled.Gate B: #13 is the load-bearing blocker and it is minutes of owner time. CTO rec. 10 and CISO finding 4 converge:
infra/firestore/firestore.rulesis deny-by-default, well-formed, committed — and never deployed. The live read boundary for every browser client is whatever was hand-set in the console, unknown and unversioned, while the frontend reads Firestore directly. This is pulled forward as the single highest-leverage owner ask this week, ahead of everything except the conversations:Owner: the human owner. Due 2026-08-31. Roughly five minutes. #51 (CI step so it can never drift again) follows and is engineering work, not owner work.
8.
board:agendaitems — all three scoped, label removed/statuscommand (directly answers "the runs produced no output") and/log <note>feeding the Decision 6a conversation counter. Hard requirement: allowlist chat id5028509822, silently ignore every other sender — no reply confirms the bot is live. Everything state-changing (/cto,/ciso,/board, anything spending money) is deferred to a CTO-scoped sitting. Answering its own question 1: yes, it earns its place, at this size only. Owner: CTO, sign-off CISO, by 2026-08-31.network_mode: hostbeside a privilegedop25with/devmounted is host-level exposure on hardware already in friends-and-family hands. Ruling: force credential rotation on first boot. Owner: CTO. It becomes the next single engineering issue for the runner. If it cannot be fixed over MQTT/WireGuard, say so explicitly and log a physical-visit date — it does not get silently reclassified as a normal code fix.ps).9. Instrumentation honesty — CTO finding 4 ADOPTED
#57 recurring correlation dump covers #5 and #35 only. It structurally cannot answer #27 (needs the call-end-to-incident-created timestamp delta, not orphan totals) or #28 (needs the one-time backfill route in
DEFERRED.md:51— a passive scan cannot surface a document nothing links to). Running it every cycle and calling those covered is ceremony that reads as diligence. #27 and #28 get comments recording this; neither is folded into #57.#45 (7 consecutive days of real AI cost against a provider invoice) has no collection mechanism — the runbook only opens the AI window when a correlation-affecting commit is live, so #45 can stall forever at zero qualifying commits. CTO proposes one explicit contiguous 7-day window with a stated dollar cap; the cap figure is owner-only money and is not being invented here. CTO comments the proposed figure on #45; owner confirms by reply.
10. Owner-hour budget — under the 5h/week hard cap
firebase deployfirestore rules (#13)gcp-key.jsonrotation (exempt per #54 decision 8)Total ≈ 3h40m. Under cap. Nothing else is asked of the owner this week, and every engineering decision above was deliberately assigned to an agent or the CTO for that reason.
Follow-up issues filed from these minutes
See the linked issues in the comment below. Existing issues touched: #46 (Gate A, partly enacted by
a1bdccf, stays open for/settings/billing), #13 (pulled forward), #56 (scoped down), #43, #48, #27, #28, #45, #51, node-26#1 (P0), node-26#4 (deferred).Document amendments enacted
GOALS.md— 2026-09-05 checkpoint stamped in (Decision 6b).BUSINESS_MODEL.md— Gate A recorded as enforced on the public site bya1bdccf..claude/skills/board/SKILL.md— cadence item struck from the founding agenda; Monday sitting now delivered by the runner.CLAUDE.md— cadence and ratification status updated.Follow-up issues filed (all live)
require_service_key_or_adminon/admin/features, distinct agent credential, single AI-on helpercompose up -d, auto-revert, fix the false notify-failure textgcp-key.jsondrb-worksession.mdEnacted in code this session:
a1bdccf(Gate A - prices off every public surface, CTAs to/waitlist,billing.tsguardrail committed,tsc --noEmitclean).Owner ruling 2026-08-26: one run per day, not two. This supersedes the twice-daily cadence in board minutes #62 (Decision 4's Monday board sitting is unaffected — it rides on whichever run falls on a Monday).
Revised command — keep
DRB Session AMat 02:37, retireDRB Session PM:Disable-rather thanUnregister-so the cadence can be reversed without rebuilding the task.drb-worksession.mdnow carries the cadence at the top of the file: there is no second bite at the day, so a run that lands nothing costs the company a full day. One engineering item and one business item, finished, beats three started.Note this raises the stakes on the supervisor in this issue: with two runs a day a silent failure cost half a day, with one it costs all of it.
logan referenced this issue2026-08-31 02:46:15 -04:00
Closing per #146 D8 (2026-09-13): a
minutes:finalissue is not a tracker. The record of a ratified decision is the stamp on the document; live work is tracked by its own work issue. Six minutes:final issues had been open 8-21 days with unexecuted decisions inside them and nobody looking.Superseded by #146. Decision 6b's 2026-09-05 checkpoint auto-trigger did not fire — that failure is itself finding 1 behind #146 D3. The beachhead test's plan of record is replaced by #146 D1/D2: the hypothesis is not dead, the owner-cold-call delivery mechanism is, and a 2026-09-16 gate with an explicit default now governs. Decisions 6c/6d survive unchanged.