plan.md
c137 plan: App Messaging, Overseer and Citizen (draft, before kick-off)
Gate: none for the design. Kicked off 2026-11-09 on Mark's word with Phases 0–2 in their own session. Phase 3 lands with c131 Phase 1, because Mark ruled the ports and bones into V1 (2026-11-09). Phase 4 lands with c134.
Defaults: D1–D8 confirmed by Mark on 2026-11-09.
Reader: Mark; c131's executor (the bones ship in V1); c133 (a training assignment is a message); c136 (a grant notice is a message); Tyler at G2 (which messages flow first).
Mode: rebellion (refuse the notification firehose and offer the person control in return) → formula (a message schema is a codified thing).
Problem: problem:enforcement-without-local-context (session 1b21a3ce, Mark Peterson, first-hand advisor; standing observed, advisor-labelled; not customer validation).
Vocabulary: overseer and citizen are Mark's working words for the two parties and stay internal; the product words come from c0 in ../qnative. The brand would never put "overseer" in a UI (powerful, not intimidating).
Why
Two parties will talk through these apps: the overseer (the control plane and the people who run it: IT, security; "Qplane, to be named") and the citizen (the employee at the endpoint, with the native app and the tray). Mark Peterson's ask is the first message: when qcontrol enforces, tell the person what happened and how to reach IT, so it is not "such a complete whiplash in vacuum of information". Mark Parson's prompt lists more: notices from HQ, confirmations of identity, censures with what to stop doing, new responsibilities, training. Each is a message. If each is built where it is needed, the person is bombarded, and the brand's promise ("invisible when working, visible when needed"; "we are not noisy") breaks on the one surface an employee actually sees.
So the ports (the channels) and the bones (the skeleton of a message) are designed once and ship with V1, even though only the Connect confirmations flow at first. The person's control over what reaches them is the design, not a settings page added later. Through the methodology: a message is a module, its type the purpose and its bones the protocol; the channel is the protocol between two modules whose internals are free. "Exquisite control" is the edge of chaos applied to attention: the overseer's freedom to send meets the citizen's order over what gets through.
The shape
The parties
| Role | Working word | Product word | Where |
|---|---|---|---|
| sends policy, notices, assignments | overseer | operator, IT (the brand already says "operators"); c0 decides | the control plane web app |
| the person at the keyboard | citizen | you, the person, end user (Peterson's word); c0 decides | the native app, the tray, the OS |
Ports (channels)
| Port | Carries | Controlled by |
|---|---|---|
| Inbox in the native app | every message, kept, with its state | the app; always on |
| Tray | a count and the one line that matters | the citizen (on · off) |
| OS notification | immediate, interruptive | the citizen, per type and with quiet hours; one override (below) |
| Web app | the operator's side of the same inbox; the pages a message links to | the overseer |
| Email, Slack | out of V1; later through the plane's integrations | — |
"Native message channels" means the OS notification centre (macOS, Windows toasts, Linux freedesktop notifications) through the kit or the platform layer; c130's platform.md finds out what the kit gives us.
Bones (the message)
Message {
id, type, severity: info | attention | required,
from: { plane, operator } | qcontrol, to: { endpoint, person },
subject (one line, 60 chars at most),
body: what happened · why it matters · what to do next,
actions: [ { label, kind: open-page | acknowledge | start-training | contact-it | dismiss, target } ],
links: { finding?, policy?, training?, grant? },
requires_ack, expires_at?, created_at,
state: new | seen | acknowledged | done | expired,
thread?: replies (a citizen's "contact IT" is a message back)
}
Every body follows the brand's rule for errors and alerts: say what happened, why it matters, and what to do next. Calm, specific, honest.
Types (the inventory from the roadmap)
- Overseer → citizen: enforcement notice (a policy acted on this machine: what, why, how to reach IT; the Peterson message) · HQ notice · identity confirmation ("this machine is connected as…") · censure ("stop doing X, Y, Z", in HQ's words) · responsibility ("you are now responsible for…") · training assignment (c133) · configuration change ("your plane changed X") · mechanic-access notice (c136).
- Citizen → overseer: acknowledgement · contact IT (with the message's context attached) · training completed (c133) · diagnostics on request (consent first, then send) · connect request.
- qcontrol → citizen, locally, with no plane: enforcement notice in local mode · sensor state (on · off · degraded).
In V1 the Connect confirmations flow; local enforcement notices if Tyler rules them in at G2 (Q5 there); the rest later.
The citizen's control
- Per type: off · inbox only · tray · notify, with sensible defaults (enforcement: notify; HQ notice: inbox; training: tray).
- Quiet hours and the OS's Focus, respected, with a digest afterwards.
- Mute a thread, or a policy's notices, for a day.
- One override: only
requiredmessages pass quiet hours. The overseer choosesrequiredsparingly, and the app shows how many required messages the overseer sent this month. Honesty in both directions. - "Why am I seeing this" on every notification: the policy or the person that sent it.
- Nothing hidden: the inbox says what the settings held back ("3 notices went to your inbox quietly"). Control never erases the record.
Rules
- R1. One schema, every message. No team adds a side channel.
- R2. Three sentences. What happened, why it matters, what to do next (the brand's alert rule).
- R3. The citizen controls delivery; the overseer controls content.
requiredis the single override, and it is counted. - R4. Nothing is alarming. Severity words are attention and required, never danger or critical, in the citizen's UI; the brand's colour rules hold (orange for work left, red only for blocked or failed).
- R5. Every message ends. Acknowledged, done or expired. The inbox is a record, not a pile.
- R6. The record is honest and bounded. The audit log keeps sent, seen and acknowledged (c133's proof of correction relies on it) and nothing about dwell or read time.
- R7. Use the OS. The platform's notification centre and its settings model before anything of our own; the app adds only what the OS lacks (per type, per policy).
Decisions (defaults)
| # | Question | Default |
|---|---|---|
| D1 | Where messages live | the plane holds the record and the operator's view; the native app keeps a local inbox (SQLite) that syncs; in local mode, messages exist locally only. |
| D2 | Transport | the plane source of c131's DataNozzle; messages are a resource like any other (bible R15), fetched or streamed; replies posted back. |
| D3 | V1 scope (Mark's ruling) | the schema in the types crate, the inbox store, the OS notification plumbing with per-type controls, the tray count, and the Connect confirmation as the one flowing type. The design of the full type set and the controls is this cycle's; the plumbing ships in c131 Phase 1. |
| D4 | The required override | allowed for enforcement and censure types by default; the overseer may set it per policy; always counted and visible. |
| D5 | Contact IT | a reply that lands in the plane's inbox and, through integrations later, Slack or email. The IT contact text comes from the plane's org settings (Peterson's "path to IT"). |
| D6 | Censures | HQ's words verbatim, labelled as from HQ, never rewritten by us (c133 R6). |
| D7 | Names | overseer and citizen stay internal; the product words come from c0. |
| D8 | Design medium | the lab for the web side; c132's medium for the native side; the OS notification itself mocked as captures per platform. |
| D9 | Delivery modes (ruled 2026-11-11) | per kind, three plain modes: quiet · normal · priority, each one OS interruption level (macOS passive · active · time-sensitive; Windows toast priority and Focus Assist). priority is the ceiling and only required may use it; never "critical" or "danger" (R4). Alert permission is asked once, at Connect, with the reason. |
| D10 | Inbox order (ruled 2026-11-11) | open required and new messages float above seen ones; within each band, by time. Supersedes bones §5. |
| D11 | The voice lint (ruled 2026-11-11) | a plane setting, voice_lint: advise | confirm, default advise; lengths and the required permission stay hard checks. |
| D12 | After an action (ruled 2026-11-11) | a short toast in the native app's notification host (c131 D8) carries the confirmation when the card moves under the fold. |
| D13 | V1 answers to ports.md §5 (ruled 2026-11-11) | no floor for enforcement notices (the person decides, tray by default); required without the entitlement is notify + tray + the inbox flag; no acknowledge from the notification; one sender label per plane; the operator's inbox at Admin › Messages; local mode's Contact IT one-way until connected. |
Phases
0. Inventory (can run now)
Every message the roadmap implies, the table above completed with its source (session, prompt, cycle) and its default delivery; the 5-question pass per type (useful, clear, precise, necessary, beautiful); the ones that fail are dropped.
1. Bones (can run now)
The schema as a document and as a types entry for ../qnative; ten example messages written in brand voice and checked with the brand MCP's voice tool; the three-sentence rule shown by them.
2. Ports and controls (can run now)
The citizen's inbox and settings mocked (c132's medium, or the lab in a native skin until it exists); the OS notification per platform as captures; the operator's send side in the lab in c134's shell. Review stop.
3. The V1 slice, with c131 Phase 1
Schema, inbox store, OS plumbing, per-type controls, tray count, the Connect confirmation flowing. A story per state.
The first native tour exercises this slice (ruled 2026-11-11, c131 D15): switch to the pilot world, simulate a bad event (the paste scare, the secret-file read or the incident; one tour or three), watch the enforcement notice arrive locally and tune what gets through. The tour's "alarm" is this cycle's enforcement notice under R4; its tuning is the citizen's controls above.
4. The plane side, with c134
The operator's inbox, send, the required policy, the audit events; the contract added to c134's API document.
5. Close
The record; the training assignment type handed to c133 and the grant notice to c136.
Clarifying questions
Does qcontrol itself send enforcement notices in local mode, before any plane exists?Yes (default held; 2026-11-11 ruled local mode's Contact IT one-way from qcontrol's config, D13).- Does the overseer see that a message was seen (R6 keeps sent, seen, acknowledged)? Any privacy line Tyler or Peterson draws?
- Which V1 messages beyond Connect does Tyler want (G2 Q5)?
- Email or Slack for the citizen: ever, or is the OS the only interruptive channel?
The tour's simulated event: which arc event does theAnswered 2026-11-11: all three (the paste scare, the secret-file read, the incident), as one tour or three if that is too much for one. Still open: whether the local notice carries the IT contact (question 1).drillinject on this machine?
Patterns to consider
- Honest Security (Kolide): device-trust messages to end users that explain and ask instead of blocking silently. The closest precedent to Peterson's ask.
- Apple's Focus and notification summary: honour them, do not fight them.
- Message as module: the same bones carry a training assignment, a grant notice, a censure. One component in the kit and one in the layer render them all.
- The brand's alert tone as a lint: the ten example messages become the voice-check fixtures for every message type that follows.
- Letters, not alerts: an HQ notice reads like a short letter from a person, signed; censures are the exception and are labelled as such.