Settings as Integration — Design Document
ARCHIVE — This document is historical reference only. It may contain outdated information. See docs/status.md for current project state.
Created: February 13, 2026 Status: Planned Phase: 3j (Settings as Integration)
Overview
Expose all Morphee settings through a conversational AI interface. Users configure the app by talking to it, not navigating UI forms.
Key insight: Settings are just another Integration — like Gmail or Calendar, but for app configuration instead of external services.
Motivation
Problem: Non-technical users (Grandparent, Kid personas) struggle with settings UIs:
- Deep navigation trees ("Settings > Notifications > Email > Quiet Hours")
- Technical jargon ("SMTP", "OAuth scopes", "API keys")
- No guidance on what to configure first
Solution: Settings as a conversational interface:
User: "Turn off email notifications at night"
AI: → settings__update_notification_preferences(type="email", quiet_hours={start: "22:00", end: "07:00"})
→ "Done! Email notifications will pause from 10pm to 7am."
User: "Change my name to Jane"
AI: → settings__update_profile(name="Jane")
→ "Updated! Your profile name is now Jane."
User: "What's our group timezone?"
AI: → settings__get_group_settings()
→ "Your group 'The Martins' is set to America/New_York."
Benefits:
- Grandparents configure by asking, not clicking
- Settings changes are auditable (stored in conversation history)
- AI can proactively suggest settings ("Would you like quiet hours for dinner time?")
- Unified API for all interfaces (CLI, voice, mobile, desktop)
Architecture
SettingsIntegration
Location: backend/interfaces/integrations/settings.py
10 actions:
get_setting(category, key?)→ current value(s) —ai_access: EXECUTEupdate_setting(category, key, value)→ updated —ai_access: PROPOSElist_categories()→ available categories —ai_access: EXECUTEget_profile()→ user profile data —ai_access: EXECUTEupdate_profile(name?, avatar_url?)→ updated —ai_access: PROPOSEget_group_settings()→ group config —ai_access: EXECUTEupdate_group_settings(name?, timezone?)→ updated —ai_access: PROPOSE(parent only)get_notification_preferences()→ notification settings —ai_access: EXECUTEupdate_notification_preferences(...)→ updated —ai_access: PROPOSEget_interface_configs()→ list of integrations —ai_access: EXECUTEconfigure_interface(name, config)→ updated —ai_access: PROPOSE(parent only)
Setting Categories & Schema
class SettingDefinition(BaseModel):
category: str
key: str
value_type: str # "string" | "number" | "boolean" | "object" | "array"
default: Any | None = None
security_level: str = "public" # "public" | "private" | "secret"
description: str
validation: dict | None = None # JSON schema for validation
requires_role: str | None = None # "parent" | None (any user)
Categories:
| Category | Keys | Storage | Scope |
|---|---|---|---|
profile | name, email, avatar_url, language | users table + user_settings | user-specific |
group | name, timezone, default_space_id | groups table | group-shared |
notifications | types, enabled, quiet_hours, sound | user_settings | user-specific |
privacy | analytics_enabled, crash_reports_enabled | user_settings | user-specific |
appearance | theme, text_size, animations_enabled | user_settings | user-specific |
integrations | interface configs | interface_configs table | group/space |
Database: User Settings Table
CREATE TABLE user_settings (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
category VARCHAR(50) NOT NULL,
key VARCHAR(100) NOT NULL,
value JSONB NOT NULL,
value_type VARCHAR(20) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(user_id, category, key)
);
CREATE INDEX idx_user_settings_user_category ON user_settings(user_id, category);
Permission Enforcement
async def update_group_settings(self, ctx: ExecutionContext, **params) -> ActionResult:
# Check if user is parent
user = await self.auth_service.get_user(ctx.user_id)
if user.role != "parent":
return ActionResult(
success=False,
error="Only parents can update group settings"
)
await self.group_service.update(ctx.group_id, **params)
return ActionResult(success=True, result={"updated": True})
Frontend: SettingsCard Renderer
New Tier 2 component: frontend/src/components/chat/renderers/SettingsCard.tsx
Renders:
- Setting preview (before confirmation)
- Confirmation buttons (Approve / Cancel)
- OAuth flow integration (e.g., "Connect Google Calendar" → GoogleConnect component)
- Success/error messages
System Prompt Guidance
Add to backend/chat/prompts.py:
SETTINGS_GUIDANCE = """
## Settings Management
You can manage user and group settings through the `settings` integration. Use these actions when users want to change configuration:
**Common examples:**
- "Change my name" → settings__update_profile(name="...")
- "Turn off notifications at night" → settings__update_notification_preferences(quiet_hours={...})
- "What's our timezone?" → settings__get_group_settings()
- "Connect Google Calendar" → settings__configure_interface("google_calendar", {...})
**Permission rules:**
- Profile updates: any user
- Notification preferences: any user
- Group settings (name, timezone): parent role only
- Integration configuration: parent role only
"""
API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/settings/{category}/{key} | GET | Get setting value |
/api/settings/{category}/{key} | PUT | Update setting |
/api/settings/categories | GET | List all setting categories |
/api/settings/profile | GET | Get user profile |
/api/settings/profile | PATCH | Update profile |
/api/settings/group | GET | Get group settings |
/api/settings/group | PATCH | Update group (parent only) |
/api/settings/notifications | GET | Get notification preferences |
/api/settings/notifications | PATCH | Update preferences |
Effort Estimation
| Task | Size | Notes |
|---|---|---|
| Backend: SettingsIntegration class | M | 10 actions + permission enforcement |
| Backend: user_settings table + migration | XS | SQL schema |
| Backend: Unified setting schema | S | SettingDefinition model + validation |
| Backend: API endpoints | M | REST API for all setting categories |
| Frontend: SettingsCard renderer | M | Tier 2 component with confirmation flow |
| Frontend: OAuth integration | S | Wire GoogleConnect to settings flow |
| System prompt guidance | XS | Add to prompts.py |
| Tests: Backend + Frontend | M | 30+ tests |
Total: Medium (1-2 weeks)
Risks & Mitigations
| Risk | Mitigation |
|---|---|
| Permission bypass | Enforce role checks in backend, not just frontend |
| Setting validation failure | JSON schema validation + user-friendly error messages |
| OAuth flow confusion | Clear UI: "Confirm → Redirecting to Google → Back to Morphee" |
| Setting conflicts (group vs user) | Clear precedence: user overrides group for appearance, group-only for shared settings |
Future Enhancements
Core Features
- Bulk settings export/import — "Export my settings as JSON", useful for migration between groups or devices
- Setting recommendations — AI suggests settings based on persona + usage patterns
- Setting presets — "Family mode", "Classroom mode" with predefined configs
- Setting history — Audit trail of all setting changes (already stored in conversation history)
- Admin UI — Web dashboard for group admins to manage all members' settings
- Setting search — "Find all settings related to notifications" → semantic search across categories
- Setting validation — Cross-setting constraints (e.g., "quiet_hours.start must be before quiet_hours.end")
ACL & Permission Enhancements
Advanced Permission Model (leveraging existing PermissionPolicy):
class SettingPermission(BaseModel):
category: str
key: str | None # None = all keys in category
can_read: list[str] # Roles: ["parent", "child", "guest"]
can_write: list[str] # Roles: ["parent"]
require_approval: bool # Setting change needs approval
approvers: list[str] # User IDs or roles who can approve
conditions: dict # Context-based rules: {"time": "weekdays_only", "location": "home"}
Use cases:
-
Parental Controls:
- Kids can read
appearance.*but notprivacy.analytics_enabled - Kids can request changes to
notifications.quiet_hours(propose mode) → parent approves - Kids can't see or modify
integrations.*(blocked)
- Kids can read
-
Classroom Scenario:
- Students can update
profile.avatar_urlbut notprofile.email - Teacher can modify
group.timezone(whole class) - Students can't change notification preferences during class hours (time-based condition)
- Students can update
-
Multi-Admin Groups:
- Both parents can modify group settings (shared parent role)
- Au pair can modify
spaces.homework.*but notintegrations.* - Grandparent (guest role) can't modify any settings, only read
Setting Approval Workflow:
- Child: "Turn off bedtime reminders" → triggers approval request
- Parent receives notification: "Emma wants to disable bedtime reminders — Approve/Reject?"
- If approved → setting changes, conversation history logs approval
- Integration with existing
ApprovalCardcomponent
Delegated Settings Management:
- Parent: "Let Emily manage her own notification settings"
- Creates temporary permission grant:
{user: emily, category: notifications, expires: "2026-12-31"} - Emily can now modify
notifications.*without approval - Stored in
delegated_permissionstable
Setting Templates with ACL:
class SettingTemplate(BaseModel):
name: str # "Homework Focus Mode"
description: str
settings: dict # {"notifications.enabled": false, "appearance.theme": "dark"}
allowed_roles: list[str] # Who can apply this template
created_by: UUID # Parent who created it
can_modify: list[str] # Who can edit this template
- Parent creates templates: "Homework Focus", "Weekend Relaxed", "Vacation Mode"
- Kids can apply templates but not modify them
- Templates stored in DB, shareable across family
Advanced Settings Features
Setting Groups & Dependencies:
- Logical grouping: "Privacy Bundle" (analytics_enabled=false, crash_reports=false, session_replay=false)
- Dependencies: Enabling
google_calendarrequiresgoogle_oauth.connected=true - AI understands dependencies: "To connect calendar, I need to set up Google OAuth first — proceed?"
Scheduled Settings Changes:
- "Turn on quiet hours every weeknight at 9pm"
- Creates cron schedule via CronIntegration:
schedule(action="settings.update", params={...}, cron="0 21 * * 1-5") - Stored in
schedulestable withaction_type: SETTING
Conditional Settings:
- Location-based: "Enable work mode when at office" (requires location permission)
- Time-based: "Dark mode after sunset" (uses timezone + sunset calculation)
- Context-based: "Disable notifications during meetings" (checks calendar via GoogleCalendarIntegration)
Setting Conflicts & Resolution:
- Detect conflicts: User sets
theme: light, but scheduled task setstheme: darkat same time - AI mediates: "You set light mode, but your scheduled task will change to dark at 8pm — cancel the schedule?"
- Conflict resolution UI shows competing settings changes
Settings Sync Across Devices:
- Desktop settings sync to mobile automatically
- Per-device overrides:
text_size: largeon mobile,text_size: mediumon desktop - Stored in
user_settingswithdevice_idfield (nullable, null = all devices)
AI-Powered Enhancements
Proactive Setting Suggestions:
- AI notices usage patterns: "You always manually disable notifications at 9pm — want to schedule it?"
- AI detects suboptimal configs: "Your text size is small, but you zoom often — increase default text size?"
- Privacy recommendations: "You haven't reviewed privacy settings in 6 months — want to check them?"
Natural Language Setting Queries:
- "What's my current theme?" →
settings.get_setting("appearance", "theme")→ "You're using dark mode" - "Show me all my notification settings" →
settings.get_setting("notifications")→ formatted summary - "When do my quiet hours start?" → extracts
quiet_hours.start→ "10pm"
Setting Impact Analysis:
- Before changing: "If I turn off analytics, you'll lose personalized recommendations — still proceed?"
- Show affected features: "Disabling calendar integration will break your morning briefing skill"
Setting Rollback:
- "Undo last 3 setting changes" → AI queries conversation history, reverts changes
- Stored in conversation:
settings__update_*tool calls have full before/after state - Can rollback to specific timestamp: "Restore my settings from last week"
Integration with Existing Systems
Settings-Aware Onboarding (Phase 1b.4):
- Onboarding flow sets initial settings based on persona
- Parent persona → enables parental controls by default
- Kid persona → restricts privacy settings, requires parent approval for changes
Settings in Skills (Phase 3b.1):
- Skills can read settings:
if settings.get("notifications.quiet_hours").active: skip_notification() - Skills can propose setting changes: "Morning briefing skill wants to enable notifications at 7am — approve?"
Settings in Memory (Phase 2):
- AI remembers setting preferences: "You prefer dark mode in evenings" → suggests auto-scheduling
- Memory stores setting change rationale: "User disabled analytics due to privacy concerns"
Settings Dashboard (Frontend):
- Visual settings editor with categories
- Real-time preview: Change theme → see live preview before saving
- Bulk actions: "Reset all notification settings to defaults"
Privacy & Security
Setting Encryption:
- Sensitive settings encrypted at rest:
privacy.*,integrations.*.credentials - Uses VaultProvider for secret storage (already implemented)
Setting Change Notifications:
- Parent receives notification when kid tries to change privacy settings
- Email + push notification: "Emma requested to disable location tracking"
GDPR Compliance:
- Settings export includes all personal data (GDPR right to access)
- Settings deletion includes cascade delete of dependent data (GDPR right to erasure)
- Consent management via settings:
privacy.gdpr_consents→ array of consent types
Last Updated: February 13, 2026