C1 spec: Experience config
Ground rules
- Values enter once, in the binding. Every Experience input lives under the experience: block of binding.yaml (the C1 band). Nothing is configured directly in a shell, a gateway file, or a template by hand.
- Everything downstream is generated. A plane change regenerates the per-tenant artifacts listed below through CI; hand-editing any generated artifact is a defect the pipeline rejects.
- Template resolution is layered. The renderer resolves templates client pack first, default pack second: a client without a custom template still renders, and adding one never touches code.
- Shells carry no configuration logic. A shell reads one generated runtime config and renders what the gateway serves. If a value would change shell code, it is in the wrong place.
REQ-E-00: omnichannel by default
Cross-channel continuity is a platform capability, not a client option. One conversation follows the person across every activated channel: the session is keyed to the person by the session and memory machinery (L7), every channel adapter and shell attaches to that session through the north gateway, and the shared UI core reconciles client-side state with it. A conversation started in chat continues on mobile, resumes on the phone, and closes in the web app with full context. Clients configure which channels are on (REQ-E-01); they do not configure whether the conversation follows the user, and no per-channel silo can be created through configuration. The only client-adjustable aspects are session handoff timeout and device-trust constraints, which are C7 security values, not C1 values.
The configuration map
Every row: the input, the discovery section that captures it, the binding key that stores it, the exact artifact it materializes into, when it takes effect, and the check that verifies it. Discovery letters refer to the interview guide and data requests on the Discovery guide page.
| ID | Client input | Disc. | Binding key | Materializes as | Takes effect | Verified by |
|---|---|---|---|---|---|---|
| E-01 | Channel activation per audience: which of chat, web, desktop, mobile, voice, phone / call center, embedded, hosts are on, for whom | G | experience.channels[] | Per-tenant north gateway config (gateway/north/tenants/<t>.yaml, channels block) + shell runtime config | On config deploy | Gateway conformance test: an inactive channel cannot open a session |
| E-02 | MCP host allow-list: which third-party hosts may connect | G | experience.hosts.allowlist[] | Same gateway config, hosts block | On config deploy | Gateway refuses any unlisted host; tested per deploy |
| E-03 | Brand and theme: logos, colors, typography | C | experience.brand_pack | One theme token file: packages/ui-core/themes/<t>.tokens.json, generated from the brand pack and served to every shell as a UI resource | Next session | Token schema check; no color or font literal anywhere in shell code |
| E-04 | House templates per document type | C | experience.template_pack@version | Client template pack templates/<t>/ in the engagement repo; renderer resolves client pack then default pack | Next output | Template completeness check: every activated use case's document types resolve |
| E-05 | Output formats per document type (PowerPoint, Word, Excel, PDF) | C | experience.output_formats{} | Renderer config renderer/config/<t>.yaml | Next output | Renderer refuses a document type with no format mapping |
| E-06 | Tone and writing style | C | experience.tone_profile | A reviewable tone guide file referenced from skills' references/; the generated client constitution points agents at it | Next run | Eval suite: style adherence scored against golden exemplars |
| E-07 | Locale conventions: currency, date, number, language(s) | C | experience.locale{} | Renderer config + ui-core formatting config; locale validated at input, never inferred at render time | Next output | Locale validation check; a missing locale blocks Gate G2 |
| E-08 | Notification rules: what may be sent proactively, to whom, over which channel, quiet hours, digest schedule and timezone | G | experience.notifications[] | Harness notification-rules config per tenant; escalation timers cross-reference the C7 values | Immediately | Rule linter: no notification path exists outside a rule |
| E-09 | Embedded surfaces: which work tools the assistant appears inside | G | experience.embedded_surfaces[] | Widget SDK config + gateway allow-list entries per surface | On config deploy | Each embedded surface authenticates as its own allow-listed entry |
| E-10 | Telephony and voice: numbers, IVR entry points, voice selection, operator console on or off | G | experience.telephony{} | Channel adapter config per tenant; speech in and out at the edge, the same gateway session behind it | On config deploy | Adapter conformance: a call attaches to the same session machinery as every other channel |
| E-11 | Surface distribution: web custom domain and SSO redirect URIs, desktop update channel, mobile distribution path | G, E | experience.surfaces{} | Generated shell runtime configs apps/<shell>/config/<t>.json (endpoint, IdP reference, enabled channels) | On shell release | Shell config schema check; IdP values come from C7, never duplicated here |
| E-12 | Review surface preferences: reading order per document type, reviewer assignment defaults | F | experience.review_ui{} | Review surface config per tenant; redundant status encoding and assistive-technology access are platform defaults, not options | Next review | Accessibility checks run on the review surface build |
| E-13 | Feedback capture scope: which user corrections may be captured as eval signal | I | experience.feedback_scope | Eval-store routing config; classification inheritance applies to everything captured | Immediately | Capture outside the scope is blocked at the routing layer, within the data-rights clause |
Where each artifact lives
The SSRA placement for everything the map above generates. Generated means exactly that: regenerated on every plane change, rejected by CI if hand-edited.
| Artifact | Repository location | Generated from | CI check |
|---|---|---|---|
| Per-tenant gateway config | pe-platform-infra/gateway/north/tenants/ | experience.channels, hosts, embedded_surfaces + C7 auth values | Schema + conformance test per deploy |
| Theme token file | pe-platform-apps/packages/ui-core/themes/ | experience.brand_pack | Token schema; literal-free shell audit |
| Client template pack | client-<name>/templates/ | Collected in discovery C; versioned with the binding | Template completeness against activated use cases |
| Renderer config | client-<name>/renderer/config/ | experience.output_formats + locale | Format mapping and locale validation |
| Shell runtime configs | pe-platform-apps/apps/*/config/ | experience.surfaces + C7 idp_config | Config schema; no secrets, vault references only |
| Notification rules | client-<name>/notifications/ | experience.notifications + C7 escalation | Rule linter |
| Tone guide | client-<name>/references/tone-guide.md | Discovery C exemplars, reviewed with the client | Referenced by generated constitution; style evals |
| Telephony adapter config | client-<name>/channels/telephony.yaml | experience.telephony | Adapter conformance test |
Acceptance: C1 configuration is complete when
- Every activated use case renders through the client template pack or the default pack, in the declared format, in the declared locale.
- Every activated channel opens, carries, and resumes the same conversation: the omnichannel walkthrough passes across at least two channels.
- The gateway conformance test proves inactive channels and unlisted hosts cannot connect.
- No shell, template, or config contains a hand-edited value: regeneration from the binding reproduces every artifact byte for byte.
- All thirteen binding keys above are valued or explicitly waived on the Decision Register; a blank key blocks Gate G2.
The ground rules and artifact-placement conventions on this page apply to the whole series, C2 through C7; those pages do not repeat them.