# Route C Config Hierachy

This document records the Route C config hierarchy for Host runtime config,
debug flags, provider params, Cloud identity, and agent-folder config.

The filename intentionally follows the requested path spelling:

```text
docs/routec/config_hierachy.md
```

## Source References

Current source owners:

```text
host-service/config.mjs
host-service/agent-config.mjs
host-service/agent-config-migration.mjs
host-service/provider-model-params.mjs
host-service/provider-model-refresh-runner.mjs
host-service/apns-config.mjs
host-service/apns-device-store.mjs
tool_scripts/sync_host_stack_config.mjs
tool_scripts/stack_dashboard_credentials.mjs
docs/routec/form_UI_fields.md
docs/routec/host_cloud_app_auth.md
```

Requirement sources:

```text
prompts/20260505_0_routeC_plan_capacitor/_requirement_proposals/05_phase_66_config_debug_file_split.md
prompts/20260505_0_routeC_plan_capacitor/_requirement_proposals/_debug_flags/README.md
prompts/20260505_0_routeC_plan_capacitor/_requirement_proposals/05_phase_56_postfix1_session_setup_notification_config_hierarchy.md
prompts/20260505_0_routeC_plan_capacitor/_requirement_proposals/05_phase_57_telegram_chat_bridge.md
prompts/20260505_0_routeC_plan_capacitor/_requirement_proposals/05_phase_59_in_session_loop_agent_folder_persistence.md
prompts/20260505_0_routeC_plan_capacitor/_requirement_proposals/05_phase_66_config_debug_file_split.md
prompts/20260505_0_routeC_plan_capacitor/_requirement_proposals/05_phase_72_agent_folder_scheduler_portability.md
```

## Core Rules

[contract] Host product config and debug config are separate.

```text
<host_config_dir>/config.json        product/runtime/user preference config
<host_config_dir>/config.debug.json  optional debug/proof/diagnostic overlay
<host_config_dir>/config.dev.json    worker HP/browser verification login source
```

[contract] `config.debug.json` is optional. If it is missing, Host uses safe
defaults and must not create the file during normal config bootstrap.

[contract] `config.dev.json` must not become a Host product runtime config
source and must not become a debug runtime flag source.

[contract] Cloud identity material belongs in `cloud_identity.json`, not in
`config.json`.

[contract] Agent shared config belongs in `<agent_folder>/.oysterun/config.json`.
Agent private/local config belongs in `<agent_folder>/.oysterun/local.json`.

[contract] `.codex/config.json` is not an Oysterun Route C session config
source.

[contract] No current Route C source-backed config path named `.security` was
found. Do not introduce `.security` as a product config layer without a new
requirement proposal and source-boundary tests.

## Host Config Directory

The Host config directory is selected by:

```text
OYSTERUN_CONFIG_DIR
```

If `OYSTERUN_CONFIG_DIR` is not set, production defaults to:

```text
~/.oysterun
```

Dev/test stacks normally use:

```text
~/.oysterun-stacks/<stack>/host
```

The selected directory is the root for Host runtime files such as `config.json`,
`config.debug.json`, `cloud_identity.json`, `params.json`, and operation logs.

## Host Runtime Files

| File / directory | Owner | Current role | Product editable? | Secret/token allowed? | Notes |
| --- | --- | --- | --- | --- | --- |
| `config.json` | Host runtime / Host Preferences / setup | Product runtime config, user-visible preferences, Host-level session defaults, dashboard password hash, provider command paths, browse root, display name, notification sound preferences. | Yes, through setup or Host Preferences for eligible fields. | Password hash yes; plaintext password no; Cloud device token no. | Source defaults come from `host-service/config.mjs`. `writeConfig()` strips debug keys and Cloud identity keys from persisted runtime storage. |
| `config.debug.json` | P66 debug split | Optional debug/proof/diagnostic overlay. | No normal product UI. | No. | Missing file returns safe defaults. Unknown keys fail fast. New debug writes target this file, not `config.json`. |
| `config.dev.json` | Verification environment | Worker HP/browser verification plaintext login credential source. | No product UI. | May contain worker login plaintext for verification only. | Product Host runtime must not read it. Startup/verification helpers can use it to materialize dashboard hash into `config.json`. |
| `cloud_identity.json` | Host Cloud auth | Host-to-Cloud identity state and credentials. | No. Host Preferences should show status only. | Yes, Host Cloud credential/token. | Stores `device_id`, `device_token`, aliases, registration state, onboarding metadata. Local Cloud dev may store non-production `backend_url`; production uses tracked code default. |
| `params.json` | P42 provider params | Current provider model/status catalog. | Not directly user-edited. | No. | Must not store APNs, dashboard credentials, command paths, Matrix/chat, scheduler/mail data, tokens, or secrets. |
| `operation_logs/provider_model_refresh.jsonl` | P42PostFix1 | Append-only provider model refresh operation log. | No. | No raw secrets. | Current operation history; `params.json` remains the current status/catalog source. |
| `apns.local.json` | Legacy/local APNs path | Local APNs p8 config for local Host-sent APNs. | No normal product UI. | Path/key metadata only; no p8 content. | Stage 1 product path uses Cloud-held p8. Local APNs config is not required for Cloud-mediated notification. |
| `apns.devices.json` | Legacy/local APNs path | Local registered APNs device store for local APNs sender. | No. | Device tokens yes. | Cloud token truth is Cloud DB for Stage 1 Cloud notification. |
| `apns-runtime-observability.jsonl` | APNs debug observability | Low-noise APNs runtime proof artifact. | No. | Token suffix only, no raw token. | Written only when both artifact and APNs observability debug gates are enabled. |
| `oysterun.sqlite` | Host DB | Host operational DB for non-Matrix product state. | No direct edit. | Depends on table. | Product chat truth is Matrix/Route C committed events, not legacy transcript rows. |
| `routec-matrix-bindings.json` | Route C Matrix facade | Host session to Matrix room binding metadata. | No. | No user edit. | Runtime artifact; do not hand-edit as a primary fix. |
| `routec-matrix-media/` and `routec-matrix-media-index.json` | Route C media facade | Matrix media file/index storage. | No. | May contain user files/media. | Runtime artifact. |
| `oysterun-matrix-artifacts/` | Route C Matrix storage/artifacts | Matrix-related runtime storage/artifacts. | No. | May contain local/runtime data. | Runtime artifact. |
| `session-history.json` | Legacy/history surface | History/session index compatibility. | No direct edit. | Local paths/session metadata possible. | Active cleanup is moving product truth away from legacy transcript surfaces. |
| `transcripts.db` | Legacy transcript DB | Deprecated legacy transcript/debug/export compatibility surface. | No. | Historical chat data possible. | New product chat truth should not depend on this file. |
| `runtime/` | Host runtime | Process/run artifacts. | No. | May contain runtime proof/path data. | Generated. |
| `secrets/` | Host-local secrets | Local secret storage when a task explicitly owns it. | No. | Yes. | Must not be committed. |

## Host `config.json`

`config.json` is normalized by `host-service/config.mjs`.

Representative product/runtime fields:

```text
port
direct_host_url
public_base_url
connection_mode
capacitor_app_id
capacitor_app_name
dashboard_user
dashboard_password_hash
dashboard_session_ttl_hours
claude_command
codex_command
default_browse_path
show_hidden_files
notification_sound_web_enabled
notification_sound_app_enabled
routec_matrix_storage_cache_enabled
transcript_retention_days
display_name
session_defaults
```

`backend_url` is exposed as a runtime value through `readConfig()` for
compatibility, but production Cloud endpoint is a tracked source default:

```text
host-service/config.mjs
PRODUCT_CLOUD_BACKEND_URL = "https://api.oysterun.com"
```

`config.json` must not persist:

```text
backend_url
host_id
host_credential
device_id
device_token
registered_at
cloud_registration_state
onboarding_token
onboarding_url
device_signing_public_key
device_signing_kid
cloud_public_key
debug_* moved by P66
telegram_feature_enabled
```

Legacy files may still contain some of these keys. Runtime normalization may
migrate them to the correct file, then remove them from persisted `config.json`.

## Host `config.debug.json`

P66 defines `config.debug.json` as the canonical debug/proof overlay:

```text
<host_config_dir>/config.debug.json
```

Current implemented allowlist:

| Key | Default | Purpose |
| --- | --- | --- |
| `debug_fixture_provider_enabled` | `false` | Enables the P33/P64 `debug-fixture` provider, displayed as `Fake` in Session Setup. |
| `debug_cloud_backend_stage` | `"prod"` | Selects Cloud stage for internal/dev routing. Encoded as `?oysterun_stage=dev|beta`; never stored in `config.json`. |
| `telegram_feature_enabled` | `false` | Locally exposes Telegram UI/runtime while Telegram remains gated. |
| `debug_host_artifact_writes_enabled` | `false` | Master gate for Host debug artifact writes. |
| `debug_routec_facade_transcript_enabled` | `false` | Matrix facade transcript JSONL/debug capture gate. |
| `debug_routec_runtime_proof_artifacts_enabled` | `false` | Route C runtime proof artifact gate. |
| `debug_apns_runtime_observability_enabled` | `false` | APNs runtime observability JSONL gate. |
| `debug_routec_facade_transcript_rotation_enabled` | `true` | Enables bounded rotation for facade transcript logs. |
| `debug_routec_facade_transcript_max_bytes` | `262144` | Bounded facade transcript max file size. |
| `debug_routec_facade_transcript_max_files` | `3` | Bounded facade transcript max file count. |
| `debug_host_preferences_full_disk_access_block_enabled` | `false` | Shows the Host Preferences macOS Folder Access recovery block for debug/manual diagnosis. Hidden in normal product setup. |

Behavior:

```text
missing config.debug.json -> safe defaults
invalid JSON -> fail fast
unknown key -> fail fast
debug key writes -> config.debug.json
product/user setting writes -> config.json
secrets -> never config.debug.json
```

Compatibility:

```text
old config.json debug fields may be read only for migration compatibility
explicit config.debug.json values supersede old config.json debug fields
config.dev.json is not a debug source
```

Related environment override:

```text
OYSTERUN_DEBUG_FIXTURE_PROVIDER=1
```

This is a non-persistent override for the Fake provider gate.

## Cloud Stage Selector

Implemented debug config key:

```text
debug_cloud_backend_stage: "prod" | "beta" | "dev"
```

Rules:

```text
missing config.debug.json -> prod
missing debug_cloud_backend_stage -> prod
base Cloud URL remains https://api.oysterun.com
stage is appended per Cloud request, e.g. ?oysterun_stage=dev
do not put ?stage=... into the base URL, because Host/app clients append paths
do not write this into config.json
do not expose this as a user Host Preference
```

The term is `stage`, not `stack`, to avoid confusion with local Host stacks
such as `test4`, `beta`, or `staging`.

The first version uses the same Cloud DB and separates rows with `cloud_stage`
columns. It does not create separate DBs or schemas for prod/beta/dev.

## Host `config.dev.json`

`config.dev.json` is for worker/browser HP verification login credentials.

Expected role:

```text
<host_config_dir>/config.dev.json
  dashboard_user
  dashboard_password
```

Rules:

```text
product Host runtime must not read config.dev.json
debug flags must not live in config.dev.json
product settings must not live in config.dev.json
browser workers may read it to log in through visible UI
startup helpers may use it to create dashboard_password_hash in config.json
plaintext values must not be printed into reports
```

If `config.dev.json` is missing during a worker HP task, classify it as
verification environment not ready. Do not ask Owner for the dashboard password
when the assigned Host folder has a valid `config.dev.json`.

## Host `cloud_identity.json`

Cloud identity path:

```text
<host_config_dir>/cloud_identity.json
```

Current allowed identity fields:

```text
backend_url
host_id
host_credential
device_id
device_token
registered_at
cloud_registration_state
onboarding_token
onboarding_url
device_signing_public_key
device_signing_kid
cloud_public_key
```

Rules:

```text
production backend URL comes from tracked code default
non-production backend_url is allowed only for explicit local Cloud development
Host Preferences shows registration status, not editable backend/token fields
device_token/host_credential are secrets
setup and registration write this file, not config.json
```

Aliases:

```text
host_id          compatibility alias for device_id
host_credential compatibility alias for device_token
```

## Host `params.json`

Provider model params path:

```text
<host_config_dir>/params.json
```

Purpose:

```text
current provider model catalog
provider model refresh status
last-known-good provider params
```

Forbidden content includes:

```text
APNs keys/tokens
dashboard credentials
provider command paths
auth tokens/secrets/private keys
Matrix/chat messages
mail data
scheduler data
session history
transcript DB rows
verification artifacts
```

`params.json` is not a general config file. It is a provider model/status
catalog only.

## Operation Logs

Provider model refresh operation log:

```text
<host_config_dir>/operation_logs/provider_model_refresh.jsonl
```

Rules:

```text
append-only operation history
no secrets
no command paths
no raw Host config
no chat/Mail/Scheduler payloads
params.json remains the current status/catalog source
```

## Cloud Deployment Secrets

Repo-local deployment secrets are not Host or agent config, but they are part
of the Cloud deployment config surface.

Local ignored file:

```text
.secrets/cloud_backend.env
```

Expected role:

```text
environment variable assignment file for deploy/install scripts
contains database URL and Cloud APNs p8 file path/key metadata
not committed
```

Remote secret/env target:

```text
/etc/oysterun-cloud/oysterun-cloud.env
/etc/oysterun-cloud/database_url
/etc/oysterun-cloud/AuthKey.p8
/etc/oysterun-cloud/metrics_admin_password
```

Stage 1 Cloud APNs signs notifications with Cloud-held p8 files. Host runtime
does not need local p8 files for Cloud-mediated notification.

## Cloud Metrics Config

P217/P219 provides a bounded aggregate summary endpoint plus a stage-aware
time-series dashboard.

Implemented storage:

```text
cloud_metric_samples
  sample_id
  bucket_start_at
  bucket_seconds = 300
  metric_name
  cloud_stage
  dimensions_json
  value
  created_at
```

Implemented charted metrics:

```text
http_requests_total
http_request_duration_ms
system.cpu_usage_percent
system.memory_used_percent
system.disk_root_used_percent
process.memory_rss_mb
```

The dashboard renders:

```text
HTTP requests
HTTP errors
Average latency
CPU usage
Memory used
Disk used
Backend RSS
APNs deliveries
```

Dashboard rendering uses two chart cards per row on desktop/tablet, one per row
on small screens, y-axis min/max ticks, and x-axis first/last bucket labels.
Percent charts use a fixed 0% to 100% scale.
The APNs deliveries chart is rendered in the first Operational Charts block;
the APNs Deliveries section below it is reserved for the latest sanitized
delivery table.

Every chart card exposes independent `1h`, `1d`, `1w`, and `1m` range controls.
The `1m` range maps to the 30-day retention window.

Retention:

```text
keep 30 days
cleanup old buckets on schedule
```

Dashboard:

```text
https://api.oysterun.com/admin/metrics
```

Password secret locations:

```text
local ignored source: .secrets/cloud_metrics_admin_password
remote file:          /etc/oysterun-cloud/metrics_admin_password
initial value:        0000
```

This is a founder-stage plaintext password file by Owner decision. It remains
outside git and must not be printed in deploy logs.

The dashboard must not expose raw APNs tokens, device tokens, password hashes,
chat content, notification body content, or p8 material.

## Agent Folder Config

Current agent config directory:

```text
<agent_folder>/.oysterun/
```

Current active files:

| File / directory | Owner | Current role | Shareable? | Secret/token allowed? | Notes |
| --- | --- | --- | --- | --- | --- |
| `.oysterun/config.json` | Agent shared config | Shared agent/session defaults. | Yes. | No. | Used by Session Setup/Profile when "Update .oysterun/config.json" is checked. |
| `.oysterun/local.json` | Agent local/private config | Private provider/web/Telegram/local overrides. | No. | Yes. | Local-only. Should not be copied into agent store packages. |
| `.oysterun/loops.json` | P59 in-session loops | Portable loop definitions. | Yes, if intended. | No. | Must not persist runtime fields such as enabled/status/last_run. |
| `.oysterun/schedulers.json` | P72 scheduler portability | Portable outside-scheduler definitions. | Yes, if intended. | No. | Must not persist run logs or secrets. |
| `.oysterun/site/` | Agent website | Static website source/assets for `/sites/<agent_id>/...`. | Yes, if intended. | No secrets. | Product site authoring surface. |
| `.oysterun/agent-store.json` | Agent Store package manifest | Agent package metadata for certified/seed agents. | Yes. | No. | Used for package validation and future install/listing. |

Legacy migration inputs:

| Legacy path | Current status |
| --- | --- |
| `<agent_folder>/.oysterun` as a file | Legacy shared config input; migrate to `.oysterun/config.json`. |
| `<agent_folder>/.oysterun.local` | Legacy local/private config input; migrate to `.oysterun/local.json`. |

## Agent Shared Config

Path:

```text
<agent_folder>/.oysterun/config.json
```

Known shared fields include:

```text
interface.provider
interface.type
interface.model
interface.reasoning_effort
interface.permission_mode
interface.approval_policy
interface.sandbox_mode
permissions.allowed_paths
runtime_capabilities
web.root
web.access
notifications.enabled
telegram.enabled
telegram.send_tool_messages
model
permission_mode
reasoning_effort
ui.default_surface
workspace_policy
```

Rules:

```text
shareable defaults only
no Telegram bot token
no Telegram allowed users
no web password hash
no provider private credentials
no APNs or Cloud identity material
```

## Agent Local Config

Path:

```text
<agent_folder>/.oysterun/local.json
```

Current local/private field groups:

```text
interface.provider_profile
interface.provider_args
interface.provider_commands
interface.provider_config_overrides
permissions.local_allowed_paths
web.password_hash
telegram.bot_token
telegram.allowed_users
```

Rules:

```text
local/private only
not shared through agent store
not written when only shared config persistence is requested
sanitized before being merged into general visible config
feature-specific resolvers may use private fields for runtime
```

## Agent Config Precedence

Session Setup/Profile config resolution uses this order:

```text
1. Built-in defaults from host-service/config.mjs
2. Host session defaults from <host_config_dir>/config.json -> session_defaults
3. Agent shared config from <agent_folder>/.oysterun/config.json
4. Sanitized agent local config from <agent_folder>/.oysterun/local.json
5. Session Setup launch payload or live Session Profile override
```

Private local fields are handled separately by feature-specific resolvers. For
example, `web.password_hash` and `telegram.bot_token` are not exposed as general
shared config.

## Session Setup / Profile Persistence

`docs/routec/form_UI_fields.md` is the UI field contract. The persistence rule
is:

```text
checked Update .oysterun/config.json
  -> persist eligible shared fields to <agent_folder>/.oysterun/config.json
  -> persist supported private/local fields to <agent_folder>/.oysterun/local.json

unchecked Update .oysterun/config.json
  -> apply to launch/live session only
  -> do not mutate agent config files
```

For a new agent folder with no `.oysterun/config.json`, the default behavior is
to create it on session start. The user may opt out through the Session Setup
"Do not create .oysterun/config.json" mode.

## In-Session Loops

Loop definition path:

```text
<agent_folder>/.oysterun/loops.json
```

Allowed definition fields:

```text
id
interval_token
interval_ms
command_text
start_at
end_at
created_at
updated_at
source
```

Forbidden runtime fields:

```text
enabled
default_enabled
status
next_run_at
last_run_at
last_status
last_error
run_count
dispatch_count
skip_count
skipped_busy_count
```

Runtime enabled/paused state is Host live-session memory state, not persisted
to `loops.json`.

## Outside Schedulers

Portable scheduler definition path:

```text
<agent_folder>/.oysterun/schedulers.json
```

Rules from P72:

```text
scheduler definitions live in schedulers.json
do not store secrets in schedulers.json
do not store run logs in schedulers.json
Host scans only Host agent folders for schedulers.json
runtime/run state remains Host-owned
```

## Website Config

Agent website config uses:

```text
<agent_folder>/.oysterun/config.json
  web.root
  web.access

<agent_folder>/.oysterun/local.json
  web.password_hash

<agent_folder>/.oysterun/site/
  static site source/assets
```

`/sites/<agent_id>/...` is the canonical Route C site URL namespace. Website
password hash is local/private and must not be written into shared config.

## Agent Store Manifest

Agent Store package manifest path:

```text
<agent_folder>/.oysterun/agent-store.json
```

Rules:

```text
package metadata only
no secrets
no local token files
no host runtime config
validate before publishing/certifying
```

## Environment Overrides

Environment variables are internal/dev/ops controls. They are not normal user
instructions in Host Preferences.

Important examples:

| Env var | Role |
| --- | --- |
| `OYSTERUN_CONFIG_DIR` | Select Host config directory. |
| `OYSTERUN_BACKEND_URL` | Explicit local Cloud/backend override. |
| `OYSTERUN_DEVICE_ID` / `OYSTERUN_DEVICE_TOKEN` | Explicit Host Cloud credential override. |
| `OYSTERUN_PORT` | Startup script writes Host port into config. |
| `OYSTERUN_STACK` / `OYSTERUN_STACKS_DIR` | Stack startup selection. |
| `OYSTERUN_STACK_DASHBOARD_USER` / `OYSTERUN_STACK_DASHBOARD_PASSWORD` | Explicit stack dashboard credential source for startup helpers. |
| `OYSTERUN_CAPACITOR_HOST_CONFIG` | Build/sync helper reads stack Host config for phone bundle target. |
| `OYSTERUN_CAPACITOR_HOST_ORIGIN` | One-off phone bundle Host origin override. |
| `OYSTERUN_DEBUG_FIXTURE_PROVIDER` | Non-persistent Fake provider debug override. |

Do not use env overrides as a product UX substitute when a value needs a real
setup or Host Preferences field.

## `.security`

Current scan result:

```text
No active Route C Host or agent-folder config source named .security was found.
```

Policy:

```text
.security is not part of the current config hierarchy
do not silently interpret it
do not use it as a fallback for permissions, secrets, auth, or provider config
future introduction requires a dedicated proposal, validation rules, and tests
```

## Summary

Short version:

```text
Host product defaults/preferences:
  <host_config_dir>/config.json

Host debug/proof flags:
  <host_config_dir>/config.debug.json

Worker login verification credential:
  <host_config_dir>/config.dev.json

Host Cloud identity:
  <host_config_dir>/cloud_identity.json

Provider model/status params:
  <host_config_dir>/params.json

Agent shared config:
  <agent_folder>/.oysterun/config.json

Agent private/local config:
  <agent_folder>/.oysterun/local.json

In-session loop definitions:
  <agent_folder>/.oysterun/loops.json

Outside scheduler definitions:
  <agent_folder>/.oysterun/schedulers.json

Agent website:
  <agent_folder>/.oysterun/site/

Agent store package metadata:
  <agent_folder>/.oysterun/agent-store.json
```
