# Owner-Isolated Diagnostic Mode — Deliberate Execution Plan

## Status
Planning only. Pending consensus and execution handoff.

## Goal
Reuse the existing single canonical-owner Telegram account and existing test bot/group for safe pre-Gate-D and incident reproduction, while preserving strict distinct-role identities in ordinary production. Identity sharing is allowed only inside an explicit, short-lived, isolated diagnostic session; role destinations remain distinct and no production customer, route, token, capability, ledger, or message may cross the boundary.

## RALPLAN-DR

### Principles
1. Production safety never inherits diagnostic exceptions.
2. Identity sharing is narrower than authority: the canonical owner may wear three test roles, but every role, destination, capability, and audit event remains explicit.
3. Diagnostic state is default-off, time-bounded, restart-fail-closed, disposable, and non-promotable.
4. Operational evidence is read-only, bounded, de-identified, and replayed only as synthetic structure.
5. Only reviewed code, schema migration, and config changes may be promoted; test state never is.

### Decision drivers
1. A solo owner must be able to reproduce the complete workflow without creating three Telegram accounts.
2. A diagnostic escape hatch must not become a production authorization bypass.
3. Incident reproduction, verification, rollback, and audit must remain deterministic and supportable.

### Options
#### A. Canonical-owner isolated session (chosen)
Pros: reuses existing setup; explicit TTL and mode boundary; production rules stay strict; supports future incidents. Cons: adds a small state machine and preflight branch.

#### B. Permanently grant a master identity all three roles
Pros: simplest operator experience. Cons: persistent confused-deputy risk; hard to distinguish test from production; violates least privilege and is rejected.

#### C. Require three Telegram accounts for every rehearsal
Pros: strongest role separation. Cons: blocks realistic solo-owner testing and does not match the established test practice; retained as the ordinary production/Gate-D default, not the diagnostic path.

## Canonical contracts

### Diagnostic session
Add an immutable `DiagnosticIsolationSession`/receipt owned by the profile authority layer with: schema version, opaque session ID, mode=`diagnostic_isolated`, canonical owner digest/version, isolated profile digest, disposable customer digest, test-bot identity digest, role destination digests, allowed operations, issue/expiry KST, status (`prepared|active|expired|revoked|closed`), predecessor and row digest. Never persist raw tokens, message bodies, customer names, or Telegram addresses in bounded receipts.

Activation requires the profile authority lock, exact current canonical owner, a disabled disposable customer, a test-only bot distinct from the configured production bot, three pairwise-distinct role chat/topic destinations, no route collision, feature epoch/delivery false, and an expiry bounded to a conservative maximum. Restart treats an `active` session as unavailable until explicit owner revalidation; expiry/revoke/close invalidates every diagnostic capability.

### Authority rule
Ordinary mode retains three distinct user identities. Diagnostic mode may use the same `user_id` only when all three role bindings equal the current canonical owner user and their `(chat_id, topic_id)` destinations are pairwise distinct. No raw `master` bypass exists. Capabilities pin `mode`, diagnostic session digest, role, destination digest, disposable customer, profile/test-bot digests, owner/config/registry/consent/activation/artifact/source/epoch pins, nonce and expiry. Production lifecycle functions reject diagnostic capabilities and diagnostic gateways reject production customers/routes.

### Read-only preflight
Extend `audit_gate_d_preflight` with an explicit typed mode/options object rather than a loose boolean. Ordinary mode preserves the current non-identical-role check. Diagnostic mode verifies canonical-owner equality, destination separation, isolated profile, disposable customer, test bot, zero production route visibility, default-off flags, TTL/session state, current KST window, schedule fence, approval artifacts, and all existing Gate-D invariants. The bounded receipt gains only mode/check/count/digest fields; it remains read-only and identifier-free.

### De-identified audit snapshot
Add a read-only `export_diagnostic_audit_snapshot(profile_root, customer_key, *, scope, requested_by)` API. It reads under the profile authority lock and emits an immutable bounded document containing schema, opaque incident/snapshot IDs, KST bounds, event-type/state sequence, counts, epochs, revision and authority/artifact digests, provider-attempt/receipt booleans, reason codes, and source digest. It excludes names, raw customer keys, messages, destinations, Telegram IDs, tokens, provider receipt contents and medical/free text. Canonical serialization failure is fatal. Export never appends operational rows.

### Isolated replay
Add `materialize_diagnostic_replay(snapshot, isolated_root, *, mapping, approved_by)` that accepts only the bounded snapshot schema and a separately approved mapping to a disposable customer and test destinations. It creates synthetic fixture state in the isolated profile, never copies production capabilities, ledgers, approval signatures, destinations, provider receipts, or customer text, and records provenance as synthetic. Path traversal, symlinks, non-isolated roots, stale snapshots and digest mismatch fail closed.

### Promotion boundary
Add a read-only promotion manifest builder for repository code paths, approved schema migrations and explicit config changes. It must reject runtime data, test customer state, messages, capabilities, ledgers, snapshots, credentials and destinations. Deployment itself remains outside this implementation unless a separately approved host deployment mechanism already exists. The runbook defines audit → reproduce → change → tests → isolated rehearsal → owner approval → deploy candidate → health check → rollback. Manual Telegram and real deployment remain human-only.

## Implementation slices

### 1. Profile authority and preflight
Targets:
- `/home/cube/.hermes/profiles/physique-coach/workspace/checkin_cli/checkin_cli/customer_admin.py`
- `/home/cube/.hermes/profiles/physique-coach/workspace/checkin_cli/checkin_cli/__init__.py`
- profile tests `tests/test_customer_admin.py`

Add typed session/options/receipt APIs, append-only session ledger validation, TTL/restart behavior, mode-aware identity rules, and bounded preflight fields. Reuse `profile_authority_lock`, `GateDPreflightReceipt`, and `validate_review_space_disjoint`; do not add generic append or direct-enable APIs.

### 2. Gateway capability and route isolation
Targets:
- `/home/cube/projects/richard/hermes-agent/gateway/platforms/nutrition_coaching_config.py`
- `/home/cube/projects/richard/hermes-agent/gateway/platforms/nutrition_coaching.py`
- `/home/cube/projects/richard/hermes-agent/gateway/platforms/telegram.py`
- focused gateway tests for nutrition coaching and group gating

Parse explicit diagnostic config/session references, mint mode-bound capabilities only after live owner/session validation, enforce role destination and disposable-customer isolation at ingress and immediately before every lifecycle/reservation/provider operation, and invalidate on expiry/restart/owner/config/session changes. Preserve Topic-59 first-match and all existing at-most-once/audit semantics.

### 3. Snapshot, replay and promotion manifest
Targets:
- Prefer a focused existing profile admin/audit module; create one narrowly named profile module only if no coherent existing module exists.
- profile tests for snapshot/replay/promotion.

Implement strict schemas and allowlists, identifier/text redaction, synthetic provenance, immutable digesting, isolated-root/path checks and promotion exclusions. No production deployment executor is introduced.

### 4. Operations documentation
Targets:
- canonical profile `PILOT_RUNBOOK.md`
- root pointer/guide/HANDOFF/report only as non-executable summaries where directly affected.

Document the ordinary-vs-diagnostic distinction, existing-environment reuse, activation/expiry/restart/cleanup, incident workflow, manual boundaries, and exact verification. Recompute the canonical runbook hash and update all pointers atomically.

## Migration and compatibility
- Existing profiles default to ordinary mode; no diagnostic session means no behavior change.
- Existing single-account settings do not silently activate diagnostics.
- Existing production capabilities cannot be upgraded or reinterpreted as diagnostic capabilities.
- Diagnostic session schema is append-only and versioned; malformed/legacy unknown rows block activation.
- Ordinary Gate-D retains the three-identity rule.
- No credential migration, registry hand-edit, or live-customer migration.

## Deliberate pre-mortem
1. Diagnostic capability reaches a real customer. Prevention: customer/profile/test-bot/destination mode pins checked at mint and pre-provider; adversarial route swap tests expect provider zero.
2. Restart revives an old session. Prevention: boot epoch plus explicit owner revalidation; stale callback/session tests expect zero rows/provider.
3. Snapshot leaks personal data. Prevention: positive field allowlist, canonical type validator, forbidden-value scanner, property tests with nested hostile input.
4. Role destinations alias despite one user. Prevention: pairwise exact `(chat_id, topic_id)` checks and reserved-space collision validation across every ingress.
5. Diagnostic artifacts are promoted. Prevention: promotion manifest allowlists repository code/schema/config only and rejects runtime roots/extensions/content classes.

## Verification plan
### Unit
- ordinary mode rejects same user; diagnostic mode accepts exact owner user only with three distinct destinations.
- default-off, TTL boundary, expiry, revoke, close, restart and boot-epoch invalidation.
- owner/config/customer/test-bot/destination/session digest mutation rejects before rows/provider.
- bounded receipt/snapshot contains no raw IDs, paths, tokens, text or receipt values.
- ledger deletion/reordering/re-digest/malformed transition fails closed.
- promotion manifest rejects every runtime/test-state class.

### Integration
- existing single-owner test bot/group can pass diagnostic preflight after disposable customer setup while ordinary preflight still fails identity collision.
- Topic-59 operator, customer and trainer role routes remain distinct with same user; every wrong route and generic fallback yields zero downstream calls.
- lifecycle P2–P6 uses diagnostic capabilities without weakening reservation, unknown, audit-pending, reconcile or cleanup contracts.
- owner rotation, TTL expiry, restart, config reload and route mutation invalidate active sessions.
- snapshot export is byte-for-byte read-only; replay writes only under isolated root and remains synthetic.

### E2E/red-team
- all Telegram ingress kinds in the diagnostic destinations; stale/forwarded/duplicate callbacks; KST rollover; incomplete check-in; low adherence; safety hold; disable/restart.
- concurrent session activation and provider reservations have one winner.
- attempted production customer/route/bot/capability injection always provider zero.
- isolated rehearsal cleanup proves all flags false, delivery revoked, overlay rolled back, disposable customer disabled, sessions revoked, scheduler/gateway stopped.
- live Telegram sends, account/token manipulation and manual P2–P6 remain explicitly unexecuted and human-owned.

### Observability
Record only opaque session/snapshot IDs, mode, role, state, bounded reason code, KST time, digest and counters. Add health checks for expired-active sessions, isolation violations, cleanup incompleteness and promotion rejection; no PII/raw destinations.

## Acceptance criteria
1. Existing production behavior and strict role separation remain unchanged by default.
2. Canonical owner can reuse one Telegram user across three diagnostic roles only in an active isolated session with distinct destinations and a disposable test customer/bot/profile.
3. Restart, expiry, owner/config/route/customer changes fail closed before provider work.
4. Preflight and snapshots are read-only, bounded and identifier-free.
5. Replay cannot import production authority/runtime state; promotion cannot include diagnostic/runtime data.
6. Focused and full profile tests, focused gateway tests and compile checks pass; unrelated pre-existing full-gateway failures are reported, never hidden.
7. Cleaner, Architect, executor QA/red-team and terminal Critic are all clean before Ultragoal completion.
8. No live Telegram operation, credential manipulation, manual P2–P6 or real-customer deployment is performed automatically.

## Intent reconciliation
The owner’s established solo testing practice is preserved only through explicit isolated diagnostics. The current production/Gate-D three-identity contract is not weakened. Problems are reported in the development session; no new Telegram natural-language diagnostic UI is added. The same diagnostic structure supports both pre-Gate-D rehearsal and future production incident reproduction.

## ADR
### Decision
Implement a canonical-owner-only, TTL-bound isolated diagnostic session with mode-bound capabilities, mode-aware preflight, de-identified snapshots, synthetic replay and a strict promotion manifest.

### Drivers
Solo-owner usability, production isolation, deterministic incident recovery.

### Alternatives considered
Permanent master identity and mandatory three-account testing; rejected as unsafe and impractical respectively.

### Consequences
More explicit state and tests, but no permanent bypass and no Telegram diagnostic control-plane expansion.

### Follow-ups
Human provisions/reuses the test Telegram environment, performs manual P2–P6 after preflight, approves any real deployment, and owns token/account actions.
