message: 403: {"code":"ENTITLEMENT_ERROR","message":"Error 403: the user is not subscribed to required model plan"}

stop_reason: error


error_message: 403: {"code":"ENTITLEMENT_ERROR","message":"Error 403: the user is not subscribed to required model plan"}


<results>
<files>
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/customer_coaching.py - core registry schema/load/validator; the one-enabled check lives here.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/customer_admin.py - register/disable/activate/runtime/preflight admission gates and writer lock.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/nutrition_onboarding_authority.py - onboarding authority validation keeps target disabled and current consent bound.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/nutrition_onboarding_cli.py - onboarding CLI loads registry/current authority.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/nutrition_onboarding_migration.py - legacy migration compatibility still hard-requires exactly one enabled customer.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/gateway/platforms/nutrition_coaching.py - production route selection hard-requires exactly one enabled route when unscoped.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/gateway/platforms/telegram_nutrition_onboarding_runtime_authority.py - registry load + customer lookup by key for onboarding runtime.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/gateway/platforms/dualcoach_activation_cutover.py - activation cutover wrapper around admin activation/validation.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/tests/test_customer_coaching_domain.py - current registry-count/identity boundary tests.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/tests/test_customer_admin.py - current direct-enable, activation, and onboarding-authority tests.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/tests/test_staff_membership_activation_gate.py - activation must fail before mutation and runtime reload must stay sealed.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/tests/gateway/test_nutrition_coaching.py - production route selection tests; good place for multi-enabled route coverage.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/tests/test_nutrition_onboarding_cli.py - migration preflight/commit schema-compat tests.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/tests/test_diagnostic_isolation.py - ordinary-vs-diagnostic registry compatibility tests.
</files>

<answer>
The one-enabled-customer restriction is enforced in multiple places, not just one:

- `customer_coaching.py:1006-1055`
  `RegistryDocument.require_unique_boundaries()` rejects `len(enabled) > 1`; `validate_pilot_customer_boundary()` repeats the count rule with a candidate; `validate_enabled_customer()` adds owner/consent checks.
  Loader path: `1109-1194` builds `CustomerRuntime` and sealed `RegisteredCustomerBinding` records.

- `customer_admin.py:660-764`
  `register_customer()` only creates disabled rows; `set_customer_enabled()` forbids direct enablement.

- `customer_admin.py:873-1118`
  `activate_customer()` loads the registry, checks `validate_pilot_customer_boundary(enabled_spec)` and `validate_enabled_customer(enabled_spec)`, then writes the enabled document.

- `customer_admin.py:1995-2058` and `4759-4804`
  runtime/rehydration gates load the registry and fail closed unless receipts are committed.

- `customer_admin.py:6499-6508`
  Gate-D preflight still requires exactly one enabled customer for the main profile containment check.

- `nutrition_onboarding_migration.py:19-42`
  legacy migration preflight requires exactly one enabled legacy customer.

- `gateway/platforms/nutrition_coaching.py:21682-21696`
  production console route selection requires exactly one enabled route unless a concrete `customer_key` is already requested.

- `nutrition_onboarding_authority.py:13-40` and `nutrition_onboarding_cli.py:64-91`
  onboarding authority is always bound to a disabled target with current consent/version.

- `gateway/platforms/telegram_nutrition_onboarding_runtime_authority.py:43-72` and `dualcoach_activation_cutover.py:42-193`
  both depend on the registry/load/activation invariants above.

Concurrency/privacy:
- `profile_authority_lock()` at `customer_admin.py:277-335` serializes all writers and rejects unsafe symlink/lock replacement.
- `CustomerRuntime.__post_init__()` and `RegisteredCustomerBinding.__post_init__()` seal path/digest integrity.
- Load paths reject symlinks/escape and duplicate data roots in `customer_coaching.py:1144-1194`.

Smallest capability-based design:
- Add a sealed admission capability/policy object with `max_enabled_customers` plus optional `selected_customer_key`.
- Keep `RegistryDocument` parse-only; move the count rule into a dedicated capability-aware validator, e.g. `validate_enabled_customer_limit(capability, candidate=None)`.
- Default capability stays `max_enabled_customers=1`, so current behavior is preserved.
- Any multi-enabled consumer must require an explicit `customer_key`; no more implicit `enabled[0]`/exactly-one fallback.

Tests that must fail first:
1. `dualcoach/profile/tests/test_customer_coaching_domain.py::test_registry_accepts_two_enabled_customers_when_limit_is_two`
   Fails today at `customer_coaching.py:1036` / `1052`.

2. `dualcoach/profile/tests/test_customer_admin.py::test_activate_customer_allows_second_enabled_customer_when_limit_is_two`
   Fails today at `customer_admin.py:949` and then `964`.

3. `tests/gateway/test_nutrition_coaching.py::test_console_requires_explicit_customer_key_when_multiple_enabled`
   Fails today at `gateway/platforms/nutrition_coaching.py:21692`.

4. `dualcoach/profile/tests/test_customer_admin.py::test_gate_d_preflight_allows_multi_enabled_under_capability`
   Fails today at `customer_admin.py:6508`.

Current tests that already pin the old rule and will need rewriting around the new capability:
- `dualcoach/profile/tests/test_customer_coaching_domain.py:425-430`
- `dualcoach/profile/tests/test_customer_admin.py:744-756`
- `dualcoach/profile/tests/test_nutrition_onboarding_cli.py:120-148`
</answer>

<next_steps>
Use the four red tests above to drive the capability thread-through, then update the existing one-enabled assertions to assert the default capability (`1`) only. Ready to proceed - no follow-up needed.
</next_steps>
</results>


<results>
<files>
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/customer_coaching.py - registry schema, load path, one-enabled validator, sealed binding/runtime, symlink/escape checks.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/customer_admin.py - register/disable/activate/reconcile/preflight/runtime gates; activation receipt/journal writes and checks.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/nutrition_onboarding_authority.py - current onboarding authority must target a disabled customer and current consent.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/nutrition_onboarding_cli.py - onboarding CLI loads current authority from registry.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/checkin_cli/nutrition_onboarding_migration.py - legacy migration preflight/commit with exactly-one enabled legacy customer.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/gateway/platforms/nutrition_coaching.py - production route selection requires exactly one enabled route when not explicitly scoped.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/gateway/platforms/telegram_nutrition_onboarding_runtime_authority.py - runtime registry lookup for onboarding messages.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/gateway/platforms/dualcoach_activation_cutover.py - activation cutover wrapper depends on admin invariants.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/tests/test_customer_coaching_domain.py - current one-enabled boundary, uniqueness, symlink, disabled-history tests.
- /home/cube/projects/richard/.worktrees/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/tests/test_customer_admin.py - current direct-enable, activation, runtime, and authority tests.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/tests/test_staff_membership_activation_gate.py - activation must fail before mutation; runtime reload stays closed.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/dualcoach/profile/tests/test_nutrition_onboarding_cli.py - migration preflight/commit compatibility checks.
- /home/cube/projects/richard/.worktrees/nutricoach-channel-inbox-v150/tests/gateway/test_nutrition_coaching.py - route selection tests, good place for multi-enabled behavior.
</files>

<answer>
Complete picture:

1) Core one-enabled-customer restriction
- `customer_coaching.py:1006-1055`
  - `RegistryDocument.require_unique_boundaries()`
    - rejects duplicate customer keys / Telegram identities / spaces
    - rejects `len(enabled) > 1` with `pilot supports only one external customer`
  - `validate_pilot_customer_boundary(candidate)` repeats the count rule across current + candidate
  - `validate_enabled_customer(spec)` adds owner/customer identity separation and local activation prereqs

2) Activation receipt/journal singularity
- `customer_admin.py:873-1118`
  - `activate_customer()` is the only enabling mutation path
  - it loads registry, checks `validate_pilot_customer_boundary(enabled_spec)`, then `validate_enabled_customer(enabled_spec)`
  - it writes the enabled registry transition only after activation proof is assembled
- `customer_admin.py:1015-1075`
  - activation writes a single pending journal, then audit + registry, then marks journal committed
  - `transaction_id` is singular per activation attempt
  - `registry_sha256` and `audit_record_sha256` are bound into one journal record
- `customer_admin.py:1820-1983`
  - `_require_committed_activation_receipt(...)` and `_validate_enabled_activation_receipts(...)` gate enabled customers
  - enabled entries must each have a committed receipt
- `customer_admin.py:1995-2058`
  - `validate_committed_activation()` fails closed unless receipt/journal state is present and valid
  - `load_runtime_customer_registry()` only returns after enabled receipts validate
- `customer_admin.py:1590-1744`
  - journal recovery path replays one activation transaction state machine and restores prior registry/audit on failure
- `customer_admin.py:6499-6508`
  - Gate-D preflight still assumes exactly one enabled customer for containment

3) Admission boundaries and callers
- Registry load callers:
  - `customer_admin.py:927, 2056, 3697, 4009, 4223, 4802, 6807`
  - `store.py:723`
  - `diagnostic_evidence.py:286`
  - `nutrition_onboarding_cli.py:69`
  - `nutrition_onboarding_authority.py:45`
- Constructor/load/mutation sites:
  - `customer_admin.py:660` register disabled draft
  - `customer_admin.py:727` disable-only setter
  - `customer_admin.py:797` withdrawal disables + consent withdrawal
  - `customer_admin.py:873` activation enables exactly one target
- Onboarding/runtime paths:
  - `nutrition_onboarding_authority.py:13-40`
  - `nutrition_onboarding_cli.py:64-91`
  - `telegram_nutrition_onboarding_runtime_authority.py:43-72`
- Production route path:
  - `gateway/platforms/nutrition_coaching.py:21682-21696`
    - if no `customer_key` is requested, exactly one enabled route is required

4) Compatibility / schema
- `customer_coaching.py:1006-1141`
  - `RegistryDocument` is versioned and supports `ordinary_v1` and `diagnostic_isolated_v1`
  - diagnostic session binding is required/forbidden depending on mode
- `nutrition_onboarding_migration.py:19-42`
  - legacy migration preflight hard-requires exactly one enabled legacy customer
- `test_diagnostic_isolation.py:1245-1280`
  - ordinary and diagnostic registries are intentionally non-interchangeable

5) Concurrency / privacy
- `customer_admin.py:277-335`
  - `profile_authority_lock()` serializes all writers and rejects unsafe symlink/replacement states
- `customer_coaching.py:1144-1194`
  - registry and customer data roots are symlink/escape checked and data roots must be unique
- `customer_coaching.py:692-732`
  - `RegisteredCustomerBinding` is sealed by token and digest-verified
- `customer_coaching.py:1064-1093`
  - runtime roots/bindings are immutable and sealed
- Privacy boundary:
  - onboarding authority rejects enabled targets: `nutrition_onboarding_authority.py:13-20`
  - current authority is only valid for disabled customer + `privacy-v1` consent

Exact minimal safe design for bounded multi-customer support:
- Introduce a sealed capability object for admission, e.g. `RegistryAdmissionCapability(max_enabled_customers: int, selected_customer_key: str | None = None)`.
- Make `RegistryDocument` remain parse-only; move enabled-count checks into a capability-aware validator.
- Default capability stays `max_enabled_customers=1`; no behavior changes for existing callers.
- Any path that currently assumes implicit single selection must require an explicit `customer_key` when `enabled_count != 1`.
- Activation/journal semantics remain singular per transaction; multi-customer support must not merge receipts or journals. Each activation still gets one journal entry/transaction id/receipt chain.
- For privacy, onboarding authority must continue to require disabled target + current consent; multi-enable must not make enabled customers routable through onboarding surfaces.

Must-fail-first tests:
- `dualcoach/profile/tests/test_customer_coaching_domain.py:425-430`
  - currently proves two enabled customers are rejected
- `dualcoach/profile/tests/test_customer_admin.py:744-756`
  - direct enable is rejected
- `dualcoach/profile/tests/test_customer_admin.py:1229-1231, 1407-1459, 1482-1483`
  - committed activation/journal recovery gate
- `dualcoach/profile/tests/test_staff_membership_activation_gate.py:28-86`
  - membership evidence faults must fail before mutation; runtime reload stays sealed
- `dualcoach/profile/tests/test_nutrition_onboarding_cli.py:120-148`
  - migration preflight/commit exactness
- `tests/gateway/test_nutrition_coaching.py:278-290`
  - route resolution expects one enabled customer
- New tests to add for bounded multi-customer capability:
  1. allow exactly N enabled only under explicit capability
  2. require explicit customer selection when >1 enabled
  3. preserve per-customer receipt/journal singularity
  4. reject onboarding authority for enabled targets even under multi-capability
  5. reject mixed ordinary/diagnostic registry reuse across capability modes

Bottom line:
- The current system is globally “single enabled customer” in both registry admission and production route selection.
- The safest relaxation is capability-gated admission with explicit selection, while keeping activation receipts/journals one-per-activation and all onboarding/privacy gates disabled-target-only.
</answer>

<next_steps>
Use the listed fail-first tests to drive a capability object through registry admission and route selection, without changing receipt/journal one-at-a-time semantics.
</next_steps>
</results>