---
title: Credentials and Confidentiality
description: Where secrets live (never the vault), how they are partitioned (per account, not per curator), why the token is held by a script rather than an agent, and the three confidentiality tiers every charter declares.
track: team
url: https://www.chiefofstaff.io/guides/credentials-and-confidentiality
published: 2026-09-01
author: chiefofstaff.io editorial system
outcome: place every credential in a per-account directory outside the vault, wrap any raw token behind a single script, and declare a confidentiality tier in every charter that controls what a curator may put in a summary.
prerequisites: manager-not-operator
source: chiefofstaff.io
---

# Credentials and Confidentiality

Where secrets live (never the vault), how they are partitioned (per account, not per curator), why the token is held by a script rather than an agent, and the three confidentiality tiers every charter declares.

## Secrets Never Enter the Vault

The vault is git-tracked, syncs across devices, and is designed to be handed to a new machine or a new person. Every one of those properties is a reason a secret must never be in it. Bot tokens, OAuth credentials, API keys, and the contributor token for this site all live under the home directory — `~/.config/<something>/` — with file mode 600, and the vault contains only the *pointer*: "the channel secret is at `~/.config/chief-of-staff/channel.secret.json`; only the coordinator reads it."

The portability test from [Files are memory](/guides/files-are-memory) applies: clone the vault somewhere new and nothing should work until you deliberately provision credentials there. That is the correct failure.

![Charters in the vault name which credential drawer to open; the drawers themselves live in the home config directory, one per account.](/img/diagrams/credentials.svg)

## Partition per Account, Not per Curator

Three curators that read the same personal Google account — email, calendar, drive — share **one** credential directory for that account. A curator for a different account gets a different directory. Each curator selects the right one per invocation by setting an environment variable the CLI reads.

Why per account rather than per curator: the credential *is* the account's identity, and pretending otherwise multiplies OAuth flows without adding isolation — the three curators can already see the same data. Where you want real isolation is between accounts, and that is exactly where the partition sits.

Prefer official CLIs with structured JSON output over heavyweight integrations. A curator that shells out to a CLI is portable, auditable in the transcript, and swaps cleanly when the runtime changes. When a tool only offers an integration that hard-codes one account, that is a reason to switch to the CLI or plain HTTP — the reference system did exactly that for three curators once multi-account auth became a requirement.

## The Token Is Held by a Script, Not the Agent

The sharpest lesson in this area came from a single incident: the channel coordinator, sending a document, wrote the bot token literally into a command line, where it appeared in the transcript. The fix was not a rule ("don't do that"). It was structural: **the token moved behind one tiny wrapper script**. The script reads the secret and makes the API call; the curator invokes the script with a method name and a payload, and never sees the value. It cannot leak what it never holds. The same wrapper appends every outbound call to the append-only history file, so the audit log is mechanical rather than a step an agent might skip.

Generalise this: any secret an agent would otherwise pass on a command line gets a wrapper.

## Three Confidentiality Tiers

Every charter declares one, and the tier controls what the curator will even put into a summary:

| Tier | Covers | Curator behaviour |
|---|---|---|
| **highly-sensitive** | personal life, health, relationships, finances, balances | summarise the *shape* ("a statement arrived; due in 9 days"), never the figures; never quote body text; escalate rather than digest when unsure |
| **internal** | companies where you are an insider | normal digest; names and figures allowed inside the system |
| **external / fractional** | clients, advisory work, other people's companies | treated more conservatively than internal — abstract counterparties in briefs, never copy their documents into the vault |

The tier also governs *where* things may go. Cloud text-to-speech, for example, is allowed only for content the chief of staff has explicitly marked public; anything else is synthesised on-device. A third-party transcription API never sees a voice note; transcription runs locally. Each of these is a decision record with the classification gate written in.

## Honour-System, Stated Honestly

Charters and tool allow-lists restrain the model; they are not operating-system sandboxes. A curator with shell access could read a file it was told not to. For a personal system this is an accepted tradeoff, recorded with its trigger — and when the trigger fires, the escalation path exists: the reference system has a design, ratified but not yet fully built, for moving the most sensitive read surface (mail) into per-account isolated virtual machines with a read-only broker between the curator and the mailbox. You almost certainly do not need that on day one. You do need to know the tradeoff you are accepting.

## Practical Checklist

- One directory per account under `~/.config/`, mode 700, files mode 600.
- No secret in any file under the vault, including `.env` files — add them to `.gitignore` anyway.
- Any token that would otherwise appear on a command line gets a wrapper script.
- Every charter names its tier; every SOP that summarises inherits the tier's limits.
- A diagnostic must never touch a live secret or history file — test against a copy. (That, too, is a feedback-log entry.)
- Rotate on any suspected exposure; the wrapper makes rotation a one-file change.