Add plugin platform with modular backend and frontend registry.

Split graph/import/meta into Django apps, add API v1 with OpenAPI and pytest, and introduce plugin registry with the tags reference plugin on both FE and BE.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-25 09:35:51 +03:00
co-authored by Cursor
parent b694a596b8
commit cafc7335ad
77 changed files with 1801 additions and 490 deletions
+50
View File
@@ -0,0 +1,50 @@
# External Plugins Policy
## Supported distribution (Phase D)
### Backend (Python)
- Package name: `social-graph-plugin-<id>`
- Entry point group: `social_graph.plugins`
- Manifest fields: `id`, `version`, `min_core_version`, `permissions[]`
Example `pyproject.toml`:
```toml
[project.entry-points."social_graph.plugins"]
tags = "social_graph_plugin_tags.plugin:TagsPlugin"
```
Install: `pip install social-graph-plugin-tags`
Enable: `ENABLED_PLUGINS=tags` in backend environment.
### Frontend (npm)
- Package name: `@social-graph/plugin-<id>`
- Default export: `PluginDefinition` (same shape as `registerPlugin()`)
Build-time inclusion only (trusted packages). Runtime CDN loading is **not supported** for security reasons.
Enable: `VITE_ENABLED_PLUGINS=tags,my-plugin`
## Trust model
| Source | Trust level | Loading |
|--------|-------------|---------|
| Monorepo `frontend/src/plugins/*` | Full | Build-time |
| npm / pip packages from allowlist | Trusted | Build-time / deploy-time |
| Arbitrary URL / user upload | Untrusted | **Blocked** |
## Version compatibility
Plugins declare `minCoreVersion`. Core version is `1.0.0` (`CORE_VERSION` in frontend, `SPECTACULAR_SETTINGS.VERSION` in backend).
Breaking API changes require a new `/api/v2/` namespace.
## Security checklist for external authors
- Request minimal `permissions`
- Do not access `localStorage` outside plugin namespace
- Do not inject scripts into core DOM outside registered extension points
- Use plugin-scoped Dexie tables only via `upgradeDexie`
+63
View File
@@ -0,0 +1,63 @@
# Plugin Author Guide
This document describes how to build **internal** plugins for Social Graph.
## Architecture overview
- **Core** owns contacts, relations, network maps, graph shell, import/export.
- **Plugins** extend the app via `registerPlugin()` without editing core files.
- **Backend** plugins are Django apps registered through `plugins.registry` and `ENABLED_PLUGINS`.
- **Frontend** plugins live under `frontend/src/plugins/<id>/` and are loaded at bootstrap.
## Frontend plugin contract
```javascript
import { registerPlugin } from '../../core/pluginRegistry'
registerPlugin({
id: 'my-plugin',
version: '1.0.0',
minCoreVersion: '1.0.0',
permissions: ['read:contacts'],
routes: [{ path: '/my', name: 'MyPlugin', component: MyView }],
navItems: [{ to: '/my', label: 'My plugin' }],
contactFormExtensions: [MyContactFieldset],
graphToolbarActions: [],
upgradeDexie(db) { /* db.version(N).stores({...}) */ },
syncContributor: {
entityType: 'plugin:my-plugin',
async pushChanges() {},
async pullChanges() {},
},
graphExtensions: {
extendNode(node) { return node },
extendEdge(edge) { return edge },
},
})
```
Enable via `VITE_ENABLED_PLUGINS=my-plugin,tags` at build time.
## Backend plugin contract
1. Create Django app under `backend/plugins_<id>/`.
2. Implement `Plugin` subclass in `plugin.py`.
3. Register in `backend/plugins/registry.py`.
4. Add app to `INSTALLED_APPS` and id to `ENABLED_PLUGINS` env var.
API surface: `/api/v1/plugins/<id>/...`
## Reference plugin: `tags`
- Frontend: `frontend/src/plugins/tags/`
- Backend: `backend/plugins_tags/`
- Dexie table: `contactTags`
- REST: `/api/v1/plugins/tags/contact-tags/`
## Local-first backup format
Plugin data should be included in backup v2+ under `plugins: { tags: [...] }` (planned extension). Current tags are stored in IndexedDB table `contactTags`.
## Permissions (Phase C)
Declared permissions are informational until JWT auth is enabled (`USE_JWT_AUTH=true`). Future scopes: `read:contacts`, `write:relations`, etc.