Skip to main content

Extensibility & Partnerships — 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: 3l (Extensibility & Partnerships)


Overview

Enable Morphee to be extended via third-party JavaScript libraries, embedded in external websites via browser extensions, and integrated by website owners via SDK. Create a partnership framework for commercial integrations.

Key capabilities:

  1. JS Library System — Load third-party libraries into Spaces with ACL-controlled permissions
  2. Browser Extension — Embed Morphee.app capabilities (chat, memory, tasks) into any website
  3. Embedding SDK — JavaScript SDK for website owners to integrate Morphee natively
  4. Partnership Framework — Commercial integration platform for B2B partnerships

Motivation

Problem: Morphee is a standalone app. Users can't:

  • Extend functionality with custom libraries (e.g., specialized calculators, domain-specific tools)
  • Use Morphee features while browsing other websites
  • Website owners can't integrate Morphee's AI capabilities into their platforms
  • No structured way for B2B partners to build on top of Morphee

Solution: Make Morphee extensible and embeddable:

  1. JS Library System — Developers package features as ACL-aware libraries loaded into Spaces
  2. Browser Extension — Floating Morphee widget available on any webpage (context-aware)
  3. Embedding SDK@morphee/sdk npm package for website integration
  4. Partnership API — Authenticated API for B2B integrations with white-labeling

Use Cases

PersonaScenario
Teacher (Emma)Loads "Math Tutor" library into Homework Space → students get interactive geometry tools in chat
DeveloperCreates custom data visualization library → publishes to Morphee Extension Store → users install with permission grants
Parent (Sophie)Uses browser extension while shopping online → "Add this to family grocery list" from any website
SaaS FounderIntegrates @morphee/sdk into customer portal → users get AI assistant with their product data context
Enterprise PartnerWhite-labels Morphee API → offers "AI Workspace powered by Morphee" to their customers

Architecture

1. JS Library System (Space Plugins)

Goal: Third-party JavaScript libraries loaded into Spaces with sandboxed execution and ACL permissions.

Library Structure

// morphee-math-tutor/index.ts
import { MorpheePlugin, PluginContext } from '@morphee/plugin-api';

export default class MathTutorPlugin implements MorpheePlugin {
name = 'math-tutor';
version = '1.0.0';
permissions = ['frontend.render', 'memory.search']; // Requested permissions

async initialize(ctx: PluginContext) {
// Register custom tools with AI
ctx.registerTool({
name: 'plot_function',
description: 'Plot a mathematical function',
parameters: {
type: 'object',
properties: {
expression: { type: 'string' },
range: { type: 'object' },
},
},
handler: async (params) => {
// Render graph using D3.js
return ctx.renderComponent({
type: 'custom_graph',
props: { expression: params.expression },
});
},
});
}
}

Backend: ExtensionsIntegration

Location: backend/interfaces/integrations/extensions.py

class ExtensionsIntegration(BaseInterface):
async def install_extension(self, ctx: ExecutionContext, extension_id: str, space_id: UUID) -> ActionResult
async def uninstall_extension(self, ctx: ExecutionContext, extension_id: str, space_id: UUID) -> ActionResult
async def list_installed(self, ctx: ExecutionContext, space_id: UUID) -> ActionResult
async def grant_permission(self, ctx: ExecutionContext, extension_id: str, permission: str) -> ActionResult
async def revoke_permission(self, ctx: ExecutionContext, extension_id: str, permission: str) -> ActionResult
async def execute_extension_action(self, ctx: ExecutionContext, extension_id: str, action: str, params: dict) -> ActionResult

Database: Extensions Tables

CREATE TABLE extensions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(100) NOT NULL UNIQUE,
display_name VARCHAR(200) NOT NULL,
description TEXT,
version VARCHAR(50) NOT NULL,
author VARCHAR(200),
icon_url TEXT,
manifest_url TEXT NOT NULL, -- HTTPS URL to extension manifest (JSON)
verified BOOLEAN DEFAULT false, -- Morphee-verified extensions
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE space_extensions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
space_id UUID NOT NULL REFERENCES spaces(id) ON DELETE CASCADE,
extension_id UUID NOT NULL REFERENCES extensions(id) ON DELETE CASCADE,
installed_by UUID NOT NULL REFERENCES users(id),
installed_at TIMESTAMPTZ DEFAULT NOW(),
enabled BOOLEAN DEFAULT true,
config JSONB DEFAULT '{}', -- Extension-specific config

UNIQUE(space_id, extension_id)
);

CREATE TABLE extension_permissions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
space_extension_id UUID NOT NULL REFERENCES space_extensions(id) ON DELETE CASCADE,
permission VARCHAR(100) NOT NULL, -- "frontend.render", "memory.search", "tasks.create"
granted_by UUID NOT NULL REFERENCES users(id),
granted_at TIMESTAMPTZ DEFAULT NOW(),

UNIQUE(space_extension_id, permission)
);

Frontend: Extension Loader

Location: frontend/src/lib/extensions/loader.ts

export class ExtensionLoader {
private loaded: Map<string, MorpheePlugin> = new Map();

async loadExtension(extensionId: string, spaceId: string): Promise<void> {
// Fetch extension manifest
const manifest = await api.get(`/api/extensions/${extensionId}/manifest`);

// Load JS bundle (sandboxed iframe or Web Worker)
const plugin = await this.loadBundle(manifest.bundle_url);

// Validate permissions
const grantedPerms = await api.get(`/api/spaces/${spaceId}/extensions/${extensionId}/permissions`);
const ctx = new PluginContext(extensionId, spaceId, grantedPerms);

// Initialize plugin
await plugin.initialize(ctx);

this.loaded.set(extensionId, plugin);
}

private async loadBundle(url: string): Promise<MorpheePlugin> {
// Option 1: Sandboxed iframe with postMessage API
// Option 2: Web Worker with structured clone
// Option 3: Dynamic import with Proxy wrapper for permission checks

// For security: CORS, Content-Security-Policy, Subresource Integrity
const response = await fetch(url, {
integrity: manifest.integrity, // SRI hash
});
const code = await response.text();

// Execute in isolated context
const worker = new Worker(URL.createObjectURL(new Blob([code], { type: 'application/javascript' })));
return new WorkerPluginWrapper(worker);
}
}

Permission Model

Extension permissions map to Integration actions:

PermissionIntegrationActionDescription
frontend.renderFrontendIntegrationshow_*Render custom components
memory.searchMemoryIntegrationsearchSearch group memory
memory.storeMemoryIntegrationstoreStore memories
tasks.createTasksIntegrationcreate_taskCreate tasks
tasks.listTasksIntegrationlist_tasksList tasks
spaces.listSpacesIntegrationlist_spacesList spaces
llm.chatLLMIntegrationchatCall LLM (token limit enforced)
network.fetch(new) NetworkIntegrationfetchHTTP requests (whitelist enforced)

ACL enforcement:

async def execute_extension_action(self, ctx: ExecutionContext, extension_id: str, action: str, params: dict):
# Check if extension has permission
perms = await self.get_extension_permissions(ctx.space_id, extension_id)
required = f"{action.split('__')[0]}.{action.split('__')[1]}" # e.g., "tasks.create"

if required not in perms:
return ActionResult(success=False, error=f"Extension missing permission: {required}")

# Check user's role allows this action in this space
user_role = await self.get_user_role(ctx.user_id, ctx.space_id)
if not self.can_execute_action(user_role, action):
return ActionResult(success=False, error="User lacks permission for this action")

# Execute action via InterfaceManager
return await self.interface_manager.execute_action(action, params, ctx)

2. Browser Extension

Goal: Floating Morphee widget on any webpage, context-aware (can read page content with permission).

Architecture

┌─────────────────────────────────────────┐
│ Any Webpage (e.g., Amazon) │
│ ┌───────────────────────────────────┐ │
│ │ Content Script (injected) │ │
│ │ - Detect page context │ │
│ │ - Show floating widget │ │
│ │ - Extract selected text │ │
│ └───────────┬───────────────────────┘ │
└──────────────┼──────────────────────────┘
│ postMessage

┌──────────────────────────────────────────┐
│ Background Service Worker │
│ - Authenticate with Morphee API │
│ - Manage WebSocket connection │
│ - Handle cross-origin requests │
└──────────────┬───────────────────────────┘
│ chrome.runtime.sendMessage

┌──────────────────────────────────────────┐
│ Popup / Sidebar (React) │
│ - Chat interface │
│ - Task quick-add │
│ - Memory search │
└──────────────────────────────────────────┘

Manifest V3 Structure

{
"manifest_version": 3,
"name": "Morphee Assistant",
"version": "1.0.0",
"permissions": [
"storage",
"activeTab",
"contextMenus"
],
"host_permissions": [
"https://api.morphee.app/*"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"css": ["widget.css"]
}
],
"action": {
"default_popup": "popup.html",
"default_icon": "icon.png"
}
}

Content Script (Injected into Pages)

Location: browser-extension/src/content.ts

// Detect page context
const pageContext = {
url: window.location.href,
title: document.title,
selectedText: window.getSelection()?.toString(),
pageType: detectPageType(), // "product", "article", "video", etc.
};

// Show floating widget
const widget = document.createElement('div');
widget.id = 'morphee-widget';
widget.innerHTML = `
<button id="morphee-trigger">
<img src="${chrome.runtime.getURL('icon.png')}" />
</button>
<div id="morphee-chat" style="display: none;">
<iframe src="${chrome.runtime.getURL('chat.html')}"></iframe>
</div>
`;
document.body.appendChild(widget);

// Listen for user clicks
document.getElementById('morphee-trigger')?.addEventListener('click', () => {
const chat = document.getElementById('morphee-chat');
chat.style.display = chat.style.display === 'none' ? 'block' : 'none';

// Send page context to chat iframe
chrome.runtime.sendMessage({
type: 'PAGE_CONTEXT',
context: pageContext,
});
});

// Context menu integration
chrome.runtime.onMessage.addListener((message) => {
if (message.type === 'ADD_TO_TASKS') {
// Selected text → create task
chrome.runtime.sendMessage({
type: 'CREATE_TASK',
title: window.getSelection()?.toString(),
url: window.location.href,
});
}
});

Background Service Worker

Location: browser-extension/src/background.ts

let wsConnection: WebSocket | null = null;

// Authenticate on extension install
chrome.runtime.onInstalled.addListener(async () => {
// Open auth flow
const authUrl = 'https://api.morphee.app/auth/extension';
const redirectUrl = chrome.identity.getRedirectURL();

chrome.identity.launchWebAuthFlow({
url: `${authUrl}?redirect_uri=${redirectUrl}`,
interactive: true,
}, (responseUrl) => {
const token = new URL(responseUrl).searchParams.get('token');
chrome.storage.local.set({ authToken: token });
});
});

// Maintain WebSocket connection
chrome.runtime.onStartup.addListener(async () => {
const { authToken } = await chrome.storage.local.get('authToken');
wsConnection = new WebSocket(`wss://api.morphee.app/ws?token=${authToken}`);

wsConnection.onmessage = (event) => {
// Broadcast to all open popups/sidebars
chrome.runtime.sendMessage({ type: 'WS_EVENT', data: JSON.parse(event.data) });
};
});

// Handle messages from content scripts
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'CREATE_TASK') {
fetch('https://api.morphee.app/api/tasks', {
method: 'POST',
headers: {
'Authorization': `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: message.title,
metadata: { source: 'browser_extension', url: message.url },
}),
}).then(() => sendResponse({ success: true }));
return true; // Async response
}
});

// Context menu
chrome.contextMenus.create({
id: 'morphee-add-task',
title: 'Add to Morphee Tasks',
contexts: ['selection'],
});

chrome.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === 'morphee-add-task') {
chrome.tabs.sendMessage(tab.id, { type: 'ADD_TO_TASKS' });
}
});

Chat Popup (React)

Location: browser-extension/src/popup/App.tsx

export function App() {
const [messages, setMessages] = useState<Message[]>([]);
const [pageContext, setPageContext] = useState<PageContext | null>(null);

useEffect(() => {
// Listen for page context
chrome.runtime.onMessage.addListener((message) => {
if (message.type === 'PAGE_CONTEXT') {
setPageContext(message.context);
}
});
}, []);

const sendMessage = async (text: string) => {
// Include page context in AI request
const enrichedPrompt = pageContext
? `Context: I'm on ${pageContext.title} (${pageContext.url}). ${text}`
: text;

const response = await fetch('https://api.morphee.app/api/chat', {
method: 'POST',
headers: {
'Authorization': `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
conversation_id: currentConversationId,
message: enrichedPrompt,
}),
});

// Handle SSE stream
const reader = response.body.getReader();
// ... (same SSE logic as web app)
};

return (
<div className="morphee-extension-popup">
<ChatBubble messages={messages} />
<ChatInput onSend={sendMessage} />
{pageContext && (
<div className="context-badge">
📄 {pageContext.title}
</div>
)}
</div>
);
}

3. Embedding SDK (@morphee/sdk)

Goal: npm package for website owners to integrate Morphee chat/tasks/memory into their apps.

Installation

npm install @morphee/sdk

Usage

import { MorpheeClient } from '@morphee/sdk';

const morphee = new MorpheeClient({
apiKey: 'mk_your_api_key', // Partner API key
groupId: 'user_group_id', // User's Morphee group
});

// Chat widget
await morphee.chat.render({
container: '#chat-widget',
theme: 'light',
initialMessage: 'Hello! How can I help you today?',
});

// Task quick-add
await morphee.tasks.create({
title: 'Follow up on customer inquiry',
spaceId: 'customer-support-space',
metadata: {
customerId: '12345',
source: 'partner_app',
},
});

// Memory search (RAG)
const results = await morphee.memory.search({
query: 'customer preferences for shipping',
spaceId: 'customer-support-space',
limit: 5,
});

// Listen to events
morphee.on('task_created', (task) => {
console.log('New task:', task);
});

SDK Architecture

// packages/sdk/src/MorpheeClient.ts
export class MorpheeClient {
private apiKey: string;
private baseUrl: string;
private ws: WebSocket | null = null;

constructor(config: MorpheeConfig) {
this.apiKey = config.apiKey;
this.baseUrl = config.baseUrl || 'https://api.morphee.app';
this.groupId = config.groupId;
}

// Chat API
chat = {
render: async (options: ChatRenderOptions) => {
const container = document.querySelector(options.container);
const iframe = document.createElement('iframe');
iframe.src = `${this.baseUrl}/embed/chat?apiKey=${this.apiKey}&theme=${options.theme}`;
container.appendChild(iframe);

// postMessage bridge for events
window.addEventListener('message', (event) => {
if (event.origin === this.baseUrl) {
this.emit(event.data.type, event.data.payload);
}
});
},

send: async (message: string, conversationId?: string) => {
return this.request('POST', '/api/chat', {
conversation_id: conversationId,
message,
});
},
};

// Tasks API
tasks = {
create: async (task: CreateTaskInput) => {
return this.request('POST', '/api/tasks', task);
},

list: async (filters?: TaskFilters) => {
return this.request('GET', '/api/tasks', filters);
},
};

// Memory API
memory = {
search: async (query: string, spaceId: string, limit = 10) => {
return this.request('POST', '/api/memory/search', {
query,
space_id: spaceId,
limit,
});
},
};

private async request(method: string, path: string, body?: any) {
const response = await fetch(`${this.baseUrl}${path}`, {
method,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
body: body ? JSON.stringify(body) : undefined,
});

if (!response.ok) {
throw new MorpheeError(response.status, await response.text());
}

return response.json();
}
}

Backend: Partner API Keys

New table:

CREATE TABLE partner_api_keys (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
key_hash VARCHAR(64) NOT NULL UNIQUE, -- bcrypt hash of "mk_..."
partner_name VARCHAR(200) NOT NULL,
group_id UUID NOT NULL REFERENCES groups(id) ON DELETE CASCADE,
scopes TEXT[] NOT NULL DEFAULT '{}', -- ["chat", "tasks", "memory"]
rate_limit_per_hour INT DEFAULT 1000,
created_by UUID NOT NULL REFERENCES users(id),
created_at TIMESTAMPTZ DEFAULT NOW(),
revoked BOOLEAN DEFAULT false
);

CREATE INDEX idx_partner_keys_hash ON partner_api_keys(key_hash) WHERE NOT revoked;

Middleware for API key auth:

# backend/auth/partner_keys.py
async def validate_partner_api_key(api_key: str) -> tuple[UUID, list[str]]:
"""Returns (group_id, scopes) if valid."""
if not api_key.startswith('mk_'):
raise ValueError("Invalid API key format")

key_hash = hash_api_key(api_key)
result = await db.fetchrow("""
SELECT group_id, scopes, rate_limit_per_hour
FROM partner_api_keys
WHERE key_hash = $1 AND NOT revoked
""", key_hash)

if not result:
raise ValueError("Invalid or revoked API key")

# Check rate limit (Redis)
usage = await redis.get(f"partner_key_usage:{key_hash}")
if usage and int(usage) >= result['rate_limit_per_hour']:
raise ValueError("Rate limit exceeded")

await redis.incr(f"partner_key_usage:{key_hash}", ex=3600)

return result['group_id'], result['scopes']

4. Partnership Framework

Goal: White-label API, revenue sharing, co-marketing platform for B2B integrations.

Partnership Tiers

TierFeaturesRevenue ShareSupport
DeveloperFree API access (1k req/month), public extension store listing70/30 (dev/Morphee)Community
Startup100k req/month, white-label embedding SDK, co-marketing60/40Email
EnterpriseUnlimited, custom SLA, dedicated account manager, on-prem optionCustomPriority

Partner Portal

Location: https://partners.morphee.app

Features:

  • API key management (create, revoke, rotate)
  • Usage analytics (requests/day, errors, latency)
  • Revenue dashboard (extension sales, usage-based billing)
  • Documentation (API reference, SDK guides, code samples)
  • Support tickets

White-Label Embedding

Partners can customize:

const morphee = new MorpheeClient({
apiKey: 'mk_partner_key',
branding: {
logo: 'https://partner.com/logo.png',
primaryColor: '#FF5722',
fontFamily: 'Inter',
name: 'Acme AI Assistant', // Replaces "Morphee" in UI
},
});

Backend stores branding in partner_api_keys.branding JSONB column.

Revenue Sharing (Extensions)

When user installs paid extension:

  1. User pays $9.99/month via Stripe
  2. Morphee takes 30% ($3.00) for hosting, API, payment processing
  3. Developer gets 70% ($6.99) deposited monthly via Stripe Connect

Database:

CREATE TABLE extension_subscriptions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
extension_id UUID NOT NULL REFERENCES extensions(id) ON DELETE CASCADE,
stripe_subscription_id VARCHAR(100) NOT NULL UNIQUE,
price_monthly_cents INT NOT NULL,
revenue_share_percent INT NOT NULL DEFAULT 70, -- Developer's share
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active, canceled, past_due
current_period_start TIMESTAMPTZ NOT NULL,
current_period_end TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),

UNIQUE(user_id, extension_id)
);

API Endpoints

Extensions API

EndpointMethodDescription
/api/extensionsGETList available extensions (marketplace)
/api/extensions/{id}GETGet extension details
/api/extensions/{id}/manifestGETGet extension manifest (JSON)
/api/spaces/{id}/extensionsPOSTInstall extension in space
/api/spaces/{id}/extensions/{ext_id}DELETEUninstall extension
/api/spaces/{id}/extensions/{ext_id}/permissionsGETList granted permissions
/api/spaces/{id}/extensions/{ext_id}/permissionsPOSTGrant permission
/api/extensions/{id}/executePOSTExecute extension action

Partner API

EndpointMethodDescription
/api/partners/keysPOSTCreate API key (parent role only)
/api/partners/keys/{id}DELETERevoke API key
/api/partners/usageGETGet usage stats
/api/partners/revenueGETGet revenue dashboard data

Embedding Endpoints (for SDK)

EndpointMethodDescription
/embed/chatGETChat widget iframe (auth via API key)
/embed/tasksGETTask widget iframe
/api/embed/chatPOSTSend chat message (API key auth)
/api/embed/tasksPOSTCreate task (API key auth)
/api/embed/memory/searchPOSTSearch memory (API key auth)

Effort Estimation

TaskSizeNotes
Backend: ExtensionsIntegrationM6 actions + ACL enforcement
Backend: Extension tables + migrationsS3 tables (extensions, space_extensions, extension_permissions)
Backend: Partner API keys + middlewareMAuth, rate limiting, scoping
Backend: Revenue sharing (Stripe Connect)MWebhook handlers, payouts
Frontend: Extension loader + sandboxLSecure iframe/Worker execution, permission UI
Frontend: Extension marketplaceMBrowse, install, configure extensions
Browser Extension: Chrome/FirefoxLManifest V3, content scripts, popup, auth flow
SDK: @morphee/sdk (npm package)MTypeScript SDK, docs, examples
Partner Portal: DashboardLReact app with analytics, revenue, docs
Documentation: Developer docs + guidesMAPI reference, SDK tutorials, extension authoring
Tests: Backend + Frontend + SDKL80+ tests total

Total: X-Large (6-8 weeks)


Risks & Mitigations

RiskMitigation
Extension security (XSS, data exfiltration)Sandboxed execution (iframe/Worker), CSP headers, permission model, code review for verified extensions
Browser extension approval delaysSubmit early to Chrome/Firefox stores, have fallback (direct install)
Partner API abuse (scraping, DDOS)Rate limiting, API key scoping, Cloudflare WAF
Revenue sharing disputesClear ToS, automated payouts, dispute resolution process
Extension conflicts (two extensions modify same UI)Extension priority system, conflict detection UI

Future Enhancements

Core Features

  • Extension Marketplace — Browse, search, install extensions with ratings/reviews
  • Extension Analytics — Track usage, errors, performance for developers
  • Extension Versioning — Semantic versioning, auto-updates, rollback
  • Extension SDK v2 — React hooks (useMemory, useTasks), Web Components
  • Mobile SDKs — iOS (Swift), Android (Kotlin) native SDKs
  • CLI for Extensionsmorphee-cli create my-extension, local dev server
  • Extension Templates — Starter templates (React component, data viz, API integration)
  • Extension Store Revenue — Premium extensions, in-app purchases

ACL & Permission Enhancements

Extension Permissions (Advanced):

interface ExtensionACL {
extension_id: string;
space_id: string;
permissions: Array<{
action: string; // "memory.search", "tasks.create"
granted_by: string; // User ID who granted
granted_at: Date;
expires_at?: Date; // Temporary permission grants
constraints?: {
rate_limit?: number; // Max calls per hour
data_scope?: string[]; // Limit to specific spaces/tags
requires_approval?: boolean; // Each call requires user approval
};
}>;
blocked_actions: string[]; // Explicitly denied permissions
sandbox_level: 'strict' | 'normal' | 'trusted';
}

Use cases:

  1. Classroom Extension Permissions:

    • Teacher installs "Plagiarism Checker" extension
    • Extension can read student submissions (memory.search scoped to homework space)
    • Cannot modify submissions (memory.store blocked)
    • Student submissions are anonymized before passing to extension
  2. Family Shopping Extension:

    • Extension can create tasks in "Shopping" space only
    • Rate limit: 10 tasks/hour (prevent spam)
    • Requires parent approval for purchases >$50
  3. Enterprise Partner White-Label:

    • Partner's extension runs in "trusted" sandbox (full API access)
    • All actions logged for compliance audit
    • Data export restricted by GDPR consent

Permission Approval Workflow:

  • Extension requests permission → User sees: "Math Tutor wants to: Search your Homework memories, Render custom graphs — Approve?"
  • Temporary grants: "Allow for 1 hour", "Allow once", "Allow always"
  • Revoke anytime: Settings → Extensions → Permissions → Revoke

Extension Isolation:

  • Each extension runs in isolated context (separate iframe/Worker)
  • Extensions cannot access each other's data
  • Shared state via PluginContext only (permission-checked)

Audit Trail:

CREATE TABLE extension_action_logs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
extension_id UUID NOT NULL REFERENCES extensions(id),
space_id UUID NOT NULL REFERENCES spaces(id),
user_id UUID NOT NULL REFERENCES users(id),
action VARCHAR(100) NOT NULL,
params JSONB,
result_success BOOLEAN,
error_message TEXT,
timestamp TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_extension_logs_user ON extension_action_logs(user_id, timestamp DESC);
  • All extension actions logged with full attribution
  • User can view: "Show all actions by 'Math Tutor' extension this week"
  • Admin dashboard: aggregate extension usage across group

Advanced Extension Features

Extension Communication:

  • Extensions can communicate via message passing (permission-checked)
  • Example: "Calendar extension" sends event to "Email extension" → creates draft email

Extension Lifecycle Hooks:

class MyPlugin implements MorpheePlugin {
async onInstall() { /* One-time setup */ }
async onUninstall() { /* Cleanup */ }
async onUpgrade(oldVersion: string) { /* Migration */ }
async onSpaceEnter(spaceId: string) { /* Context switch */ }
async onSpaceLeave(spaceId: string) { /* Cleanup */ }
}

Extension Configuration UI:

  • Extensions define config schema (JSON Schema)
  • Auto-generated settings UI in Morphee app
  • Example: "OpenAI API Key", "Preferred units (metric/imperial)"

Extension Data Storage:

# Backend: ExtensionsIntegration
async def get_extension_data(self, ctx: ExecutionContext, extension_id: str, key: str) -> ActionResult
async def set_extension_data(self, ctx: ExecutionContext, extension_id: str, key: str, value: Any) -> ActionResult
  • Per-extension KV store (scoped to space)
  • Encrypted at rest (VaultProvider)
  • Quota enforced (10MB per extension per space)

Browser Extension Enhancements

Context-Aware Features:

  • Detect page type (e-commerce, article, video) → suggest relevant actions
  • Example: On Amazon product page → "Add to family wishlist", "Compare prices with saved products"
  • Example: On YouTube video → "Save to 'Watch Later' space", "Summarize video transcript"

Offline Mode:

  • Browser extension works offline using IndexedDB cache
  • Queue actions (create task, save memory) → sync when online

Multi-Account Support:

  • Switch between Morphee accounts (work, personal, family)
  • Separate auth tokens, different group contexts

Privacy Controls:

  • User can whitelist/blacklist domains for context extraction
  • Example: "Never read banking websites", "Only extract context from work domains"

Keyboard Shortcuts:

  • Cmd+Shift+M → Open Morphee chat
  • Cmd+Shift+T → Quick-add task from selection
  • Cmd+Shift+S → Save page to memory

Embedding SDK Enhancements

Framework-Specific SDKs:

// React
import { MorpheeProvider, useChat, useTasks } from '@morphee/react';

function App() {
return (
<MorpheeProvider apiKey="mk_...">
<ChatWidget />
</MorpheeProvider>
);
}

function ChatWidget() {
const { messages, send } = useChat();
return <div>{/* ... */}</div>;
}

// Vue, Angular, Svelte versions

Customizable Components:

await morphee.chat.render({
container: '#chat',
components: {
// Replace default components with custom ones
MessageBubble: MyCustomBubble,
TaskCard: MyCustomTaskCard,
},
css: `
.morphee-chat { border-radius: 16px; }
.morphee-message { font-family: 'Comic Sans MS'; }
`,
});

Webhooks:

  • Partner app receives real-time events via webhooks
  • Example: POST https://partner.com/webhooks/morphee when task created
  • Signed with HMAC for security

Partnership Enhancements

Co-Marketing Platform:

  • Joint blog posts, webinars, case studies
  • Partner directory: "Morphee Works With" (logos, links)
  • Referral program: Partner refers customer → 10% recurring commission

White-Label On-Prem:

  • Enterprise partners can deploy Morphee on their infrastructure
  • Docker Compose + Kubernetes manifests
  • Single-tenant isolation, custom domain

API Versioning:

  • Semantic versioning: v1, v2, etc.
  • Deprecated endpoints supported for 12 months
  • Migration guides for partners

Partner Success Metrics:

  • Dashboard: MAU, API success rate, avg latency, revenue
  • Alerts: "API error rate >5%", "Usage spike detected"

Compliance & Certifications:

  • SOC 2 Type II (for enterprise partners)
  • GDPR compliance (data processing agreements)
  • HIPAA support (for healthcare partners)

Integration with Existing Systems

Extension + Skills Integration (Phase 3b.1):

  • Extensions can define skills: "Math Tutor extension provides 'Solve Equation' skill"
  • Skills can call extension actions
  • Dynamic skill registration via extension manifest

Extension + Memory Integration (Phase 2):

  • Extensions can embed custom data types in LanceDB
  • Example: "Code Snippet extension" embeds code with syntax-aware search
  • Per-extension memory namespace isolation

Extension + Frontend Integration (Phase 3b.2):

  • Extensions can register custom ComponentSpec renderers
  • Example: "Chart extension" renders { type: 'custom_chart', props: {...} }

Extension + Notifications (Phase 3a):

  • Extensions can send notifications: ctx.notify({ title, body })
  • User can configure: "Mute notifications from 'Weather' extension"

Privacy & Security

Extension Code Review:

  • All extensions submitted to marketplace undergo security review
  • Static analysis: detect API calls, data exfiltration attempts
  • Manual review for verified extensions

Extension Sandboxing (Advanced):

  • Extensions run in separate process (Tauri sidecar)
  • Memory isolation, no shared state except via IPC
  • CPU/memory quotas enforced

Extension Permissions (Runtime Checks):

// In extension code
await ctx.memory.search(query); // ❌ Throws if "memory.search" not granted

// Graceful degradation
if (ctx.hasPermission('memory.search')) {
const results = await ctx.memory.search(query);
} else {
showMessage('This extension needs memory search permission');
}

User Data Privacy:

  • Extensions cannot access other extensions' data
  • User can export all data stored by extensions (GDPR)
  • User can delete all extension data on uninstall

Partner API Security:

  • API keys rotated every 90 days (automated email reminder)
  • IP whitelisting for enterprise partners
  • Anomaly detection: unusual usage patterns trigger alerts

Last Updated: February 13, 2026