Skip to main content

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:

  1. get_setting(category, key?) → current value(s) — ai_access: EXECUTE
  2. update_setting(category, key, value) → updated — ai_access: PROPOSE
  3. list_categories() → available categories — ai_access: EXECUTE
  4. get_profile() → user profile data — ai_access: EXECUTE
  5. update_profile(name?, avatar_url?) → updated — ai_access: PROPOSE
  6. get_group_settings() → group config — ai_access: EXECUTE
  7. update_group_settings(name?, timezone?) → updated — ai_access: PROPOSE (parent only)
  8. get_notification_preferences() → notification settings — ai_access: EXECUTE
  9. update_notification_preferences(...) → updated — ai_access: PROPOSE
  10. get_interface_configs() → list of integrations — ai_access: EXECUTE
  11. configure_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:

CategoryKeysStorageScope
profilename, email, avatar_url, languageusers table + user_settingsuser-specific
groupname, timezone, default_space_idgroups tablegroup-shared
notificationstypes, enabled, quiet_hours, sounduser_settingsuser-specific
privacyanalytics_enabled, crash_reports_enableduser_settingsuser-specific
appearancetheme, text_size, animations_enableduser_settingsuser-specific
integrationsinterface configsinterface_configs tablegroup/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

EndpointMethodDescription
/api/settings/{category}/{key}GETGet setting value
/api/settings/{category}/{key}PUTUpdate setting
/api/settings/categoriesGETList all setting categories
/api/settings/profileGETGet user profile
/api/settings/profilePATCHUpdate profile
/api/settings/groupGETGet group settings
/api/settings/groupPATCHUpdate group (parent only)
/api/settings/notificationsGETGet notification preferences
/api/settings/notificationsPATCHUpdate preferences

Effort Estimation

TaskSizeNotes
Backend: SettingsIntegration classM10 actions + permission enforcement
Backend: user_settings table + migrationXSSQL schema
Backend: Unified setting schemaSSettingDefinition model + validation
Backend: API endpointsMREST API for all setting categories
Frontend: SettingsCard rendererMTier 2 component with confirmation flow
Frontend: OAuth integrationSWire GoogleConnect to settings flow
System prompt guidanceXSAdd to prompts.py
Tests: Backend + FrontendM30+ tests

Total: Medium (1-2 weeks)


Risks & Mitigations

RiskMitigation
Permission bypassEnforce role checks in backend, not just frontend
Setting validation failureJSON schema validation + user-friendly error messages
OAuth flow confusionClear 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:

  1. Parental Controls:

    • Kids can read appearance.* but not privacy.analytics_enabled
    • Kids can request changes to notifications.quiet_hours (propose mode) → parent approves
    • Kids can't see or modify integrations.* (blocked)
  2. Classroom Scenario:

    • Students can update profile.avatar_url but not profile.email
    • Teacher can modify group.timezone (whole class)
    • Students can't change notification preferences during class hours (time-based condition)
  3. Multi-Admin Groups:

    • Both parents can modify group settings (shared parent role)
    • Au pair can modify spaces.homework.* but not integrations.*
    • 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 ApprovalCard component

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_permissions table

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_calendar requires google_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 schedules table with action_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 sets theme: dark at 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: large on mobile, text_size: medium on desktop
  • Stored in user_settings with device_id field (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