domma-cms 1.6.60 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4349 -0
- package/README.md +1 -1
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +3 -3
- package/admin/js/lib/effect-defs.js +1 -1
- package/admin/js/lib/effects-builder.js +2 -2
- package/admin/js/lib/mail-compose.js +1 -0
- package/admin/js/lib/page-editor-reference.js +5 -5
- package/admin/js/lib/shortcode-tags.js +1 -1
- package/admin/js/templates/call-new.html +1 -1
- package/admin/js/templates/docs/usage-shortcodes.html +39 -0
- package/admin/js/views/call-new.js +1 -1
- package/admin/js/views/contacts.js +15 -15
- package/admin/js/views/form-submissions.js +2 -2
- package/docs/DommaFeatures.md +3005 -0
- package/docs/MultiTenant.md +176 -0
- package/docs/api-reference.md +1667 -0
- package/docs/cache.md +96 -0
- package/docs/configuration.md +1811 -0
- package/docs/editions-and-licences.md +190 -0
- package/docs/getting-started.md +201 -0
- package/docs/guides/form-triggers.md +260 -0
- package/docs/guides/mongodb-storage-adapter.md +282 -0
- package/docs/guides/multi-page-forms.md +121 -0
- package/docs/images/scribe-composer.png +0 -0
- package/docs/markdown-shortcodes.md +1738 -0
- package/docs/pentest-report-2026-04-03.md +181 -0
- package/docs/plans/2026-02-28-admin-topbar-login-forms.md +349 -0
- package/docs/plans/2026-02-28-domma-ui-polish.md +286 -0
- package/docs/plans/2026-02-28-reset-seed-fresh-commands.md +520 -0
- package/docs/plans/2026-03-02-cookie-consent-design.md +86 -0
- package/docs/plans/2026-03-02-cookie-consent-plugin.md +453 -0
- package/docs/plans/2026-03-02-tooltip-sweep-and-back-to-top-plugin-design.md +126 -0
- package/docs/plans/2026-03-02-tooltip-sweep-back-to-top.md +427 -0
- package/docs/plans/2026-03-05-cookie-consent-btt-core.md +115 -0
- package/docs/plans/2026-03-05-custom-css-migrate-to-core-design.md +35 -0
- package/docs/plans/2026-03-05-custom-css-migrate-to-core.md +352 -0
- package/docs/plans/2026-03-05-scribe-script-shortcode.md +373 -0
- package/docs/plans/2026-03-05-user-types-design.md +139 -0
- package/docs/plans/2026-03-05-user-types-implementation.md +1035 -0
- package/docs/plans/2026-03-09-page-editor-view-cta-inserts-design.md +78 -0
- package/docs/plans/2026-03-09-page-editor-view-cta-inserts.md +388 -0
- package/docs/plans/2026-03-09-pro-documentation-design.md +80 -0
- package/docs/plans/2026-03-09-pro-documentation.md +1017 -0
- package/docs/plans/2026-06-10-core-project-design.md +240 -0
- package/docs/plugin-development.md +827 -0
- package/docs/recruitment-recipe.md +501 -0
- package/docs/scaffolding.md +312 -0
- package/docs/screenshots/calculator-floating.png +0 -0
- package/docs/screenshots/calculator-standard.png +0 -0
- package/docs/screenshots/email-settings.png +0 -0
- package/docs/screenshots/messages-count.png +0 -0
- package/docs/structure/user-types.md +107 -0
- package/docs/superpowers/plans/2026-05-25-admin-sidebar-via-menus.md +1112 -0
- package/docs/superpowers/plans/2026-06-08-navbar-mobile-drawer-and-menu-enrichment.md +1161 -0
- package/docs/superpowers/plans/2026-06-25-domma-docs-project.md +695 -0
- package/docs/superpowers/plans/2026-06-26-surveys-HANDOFF.md +68 -0
- package/docs/superpowers/plans/2026-06-26-surveys-pro-plugin.md +1902 -0
- package/docs/superpowers/plans/2026-08-19-collection-context-sort-export.md +1577 -0
- package/docs/superpowers/plans/2026-10-09-content-api.md +1192 -0
- package/docs/superpowers/specs/2026-03-12-form-followup-actions-design.md +152 -0
- package/docs/superpowers/specs/2026-03-12-page-editor-form-insert-and-per-page-theme-design.md +115 -0
- package/docs/superpowers/specs/2026-03-17-nav-hidden-items-design.md +85 -0
- package/docs/superpowers/specs/2026-03-19-accordion-insert-design.md +175 -0
- package/docs/superpowers/specs/2026-03-25-static-block-shortcode-design.md +153 -0
- package/docs/superpowers/specs/2026-03-25-text-shortcode-design.md +168 -0
- package/docs/superpowers/specs/2026-04-05-card-builder-design.md +315 -0
- package/docs/superpowers/specs/2026-04-06-insert-builders-design.md +278 -0
- package/docs/superpowers/specs/2026-04-06-layouts-design.md +226 -0
- package/docs/superpowers/specs/2026-04-07-blog-plugin-design.md +300 -0
- package/docs/superpowers/specs/2026-04-07-calendar-plugin-design.md +538 -0
- package/docs/superpowers/specs/2026-04-17-components-area-design.md +368 -0
- package/docs/superpowers/specs/2026-05-02-effects-slideover-overhaul-design.md +193 -0
- package/docs/superpowers/specs/2026-05-06-dashboard-rebuild-design.md +257 -0
- package/docs/superpowers/specs/2026-05-24-menus-design.md +466 -0
- package/docs/superpowers/specs/2026-05-25-admin-sidebar-via-menus-design.md +358 -0
- package/docs/superpowers/specs/2026-05-25-projects-design.md +380 -0
- package/docs/superpowers/specs/2026-06-08-navbar-mobile-drawer-and-menu-enrichment-design.md +292 -0
- package/docs/superpowers/specs/2026-06-08-sidebar-tools-plugins-folders-design.md +59 -0
- package/docs/superpowers/specs/2026-06-25-domma-docs-project-design.md +192 -0
- package/docs/superpowers/specs/2026-06-26-domma-charts-upstream-proposal.md +44 -0
- package/docs/superpowers/specs/2026-06-26-manager-scheduler-upstream-proposal.md +46 -0
- package/docs/superpowers/specs/2026-06-26-surveys-pro-plugin-design.md +206 -0
- package/docs/superpowers/specs/2026-07-02-shortcode-context-menu-design.md +96 -0
- package/docs/superpowers/specs/2026-08-19-collection-context-sort-export-design.md +330 -0
- package/docs/superpowers/specs/2026-09-22-dcms-marketplace-design.md +1150 -0
- package/docs/superpowers/specs/2026-10-09-content-api-design.md +325 -0
- package/docs/superpowers/specs/plans/2026-03-12-form-followup-actions.md +624 -0
- package/docs/superpowers/specs/plans/2026-03-12-page-editor-form-insert-and-per-page-theme.md +125 -0
- package/docs/superpowers/specs/plans/2026-03-17-nav-hidden-items.md +578 -0
- package/docs/superpowers/specs/plans/2026-03-19-accordion-insert.md +635 -0
- package/docs/superpowers/specs/plans/2026-03-25-text-shortcode.md +545 -0
- package/docs/superpowers/specs/plans/2026-04-05-card-builder.md +1970 -0
- package/docs/superpowers/specs/plans/2026-04-06-insert-builders.md +1049 -0
- package/docs/superpowers/specs/plans/2026-04-06-layouts.md +1015 -0
- package/docs/superpowers/specs/plans/2026-04-07-calendar-plugin.md +1526 -0
- package/docs/superpowers/specs/plans/2026-04-08-plugin-monetisation-split.md +242 -0
- package/docs/superpowers/specs/plans/2026-04-17-components-area.md +2038 -0
- package/docs/superpowers/specs/plans/2026-05-02-effects-slideover-overhaul.md +2335 -0
- package/docs/superpowers/specs/plans/2026-05-06-dashboard-rebuild.md +1999 -0
- package/docs/superpowers/specs/plans/2026-05-17-cache-system.md +1436 -0
- package/docs/superpowers/specs/plans/2026-05-24-menus.md +3096 -0
- package/docs/superpowers/specs/plans/2026-05-25-projects.md +2869 -0
- package/docs/superpowers/specs/plans/2026-09-22-marketplace-step2-consolidation.md +505 -0
- package/docs/superpowers/specs/plans/2026-09-22-marketplace-step3-catalogue-and-key.md +154 -0
- package/docs/superpowers/specs/plans/2026-09-22-tools-promotion.md +260 -0
- package/docs/theming.md +320 -0
- package/package.json +2 -2
- package/plugins/_lib/admin/mail/compose-window.js +3 -1
- package/plugins/_lib/admin/mail/identity.js +18 -3
- package/plugins/_lib/admin/mail/reader-view.js +32 -3
- package/plugins/blog/CLAUDE.md +4 -0
- package/plugins/blog/admin/lib/email.js +191 -0
- package/plugins/blog/admin/views/comments.js +3 -1
- package/plugins/blog/plugin.json +2 -2
- package/plugins/blog/plugin.public.js +1 -1
- package/plugins/blog/tests/email.test.js +69 -0
- package/plugins/booking/CLAUDE.md +4 -0
- package/plugins/booking/admin/lib/email.js +191 -0
- package/plugins/booking/admin/views/panels.js +7 -3
- package/plugins/booking/plugin.json +1 -1
- package/plugins/booking/tests/email.test.js +69 -0
- package/plugins/free-tier.lock.json +27 -19
- package/plugins/shopping-cart/CLAUDE.md +4 -0
- package/plugins/shopping-cart/admin/lib/email.js +191 -0
- package/plugins/shopping-cart/admin/views/orders.js +11 -3
- package/plugins/shopping-cart/plugin.json +2 -2
- package/plugins/shopping-cart/tests/email.test.js +69 -0
- package/plugins/support/CLAUDE.md +4 -0
- package/plugins/support/admin/lib/email.js +191 -0
- package/plugins/support/admin/views/desk.js +4 -1
- package/plugins/support/admin/views/inbox.js +6 -2
- package/plugins/support/plugin.json +2 -2
- package/plugins/support/tests/email.test.js +69 -0
- package/public/js/celebrations/core/canvas.js +1 -1
- package/public/js/celebrations/index.js +1 -1
- package/public/js/celebrations/licenses/ABeeZee-Regular-OFL.txt +93 -0
- package/public/js/celebrations/licenses/Allura-Regular-OFL.txt +93 -0
- package/public/js/celebrations/message-attrs.mjs +1 -0
- package/public/js/celebrations/themes/anniversary.js +1 -0
- package/public/js/celebrations/themes/autumn.js +1 -0
- package/public/js/celebrations/themes/birthday.js +1 -0
- package/public/js/celebrations/themes/butterfly-flight.js +1 -0
- package/public/js/celebrations/themes/calendar.js +1 -0
- package/public/js/celebrations/themes/chinese-new-year-dates.js +1 -0
- package/public/js/celebrations/themes/chinese-new-year.js +1 -0
- package/public/js/celebrations/themes/christmas.js +1 -1
- package/public/js/celebrations/themes/easter.js +1 -0
- package/public/js/celebrations/themes/garden-drawing.js +1 -0
- package/public/js/celebrations/themes/garden.js +1 -0
- package/public/js/celebrations/themes/graduation.js +1 -0
- package/public/js/celebrations/themes/greeting.js +1 -0
- package/public/js/celebrations/themes/make-it-rain.js +1 -0
- package/public/js/celebrations/themes/money-rain.js +1 -0
- package/public/js/celebrations/themes/new-year.js +1 -0
- package/public/js/celebrations/themes/occasion-drawing.js +1 -0
- package/public/js/celebrations/themes/occasions.js +1 -0
- package/public/js/celebrations/themes/rain-control.js +1 -0
- package/public/js/celebrations/themes/sparkler-font-data.js +1 -0
- package/public/js/celebrations/themes/sparkler-font.js +1 -0
- package/public/js/celebrations/themes/sparkler-writing.js +1 -0
- package/public/js/celebrations/themes/summer-garden.js +1 -0
- package/public/js/celebrations/themes/winter.js +1 -0
- package/public/js/celebrations/trait-data.mjs +1 -1
- package/public/js/effects.js +1 -1
- package/scripts/build.js +4 -0
- package/server/services/markdown.js +5 -2
- package/server/templates/page.html +1 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Domma CMS - Plugin Monetisation Split
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
Domma CMS (public, distributable via npm) and Domma CMS Manager (private console
|
|
6
|
+
for registration, management, and licensing) currently have a **one-way integration**:
|
|
7
|
+
the manager can push notifications into a CMS instance via `requireManager`
|
|
8
|
+
(HMAC-verified `MANAGER_SECRET`), but the CMS never calls out to the manager.
|
|
9
|
+
|
|
10
|
+
Plugin development today happens entirely inside `domma-cms`, meaning every plugin
|
|
11
|
+
- including commercial-quality ones - is shipped source-open to anyone who
|
|
12
|
+
`npm install`s the package. That's fine for core plugins but wrong for anything
|
|
13
|
+
we want to monetise.
|
|
14
|
+
|
|
15
|
+
The goal: formalise a tiered plugin model so core plugins stay free and open in
|
|
16
|
+
`domma-cms`, and paid plugins live privately in `domma-cms-manager` and are
|
|
17
|
+
fetched on demand by licensed CMS instances via a signed registry.
|
|
18
|
+
|
|
19
|
+
## Current plugin audit
|
|
20
|
+
|
|
21
|
+
Based on an LOC + scope audit of `plugins/` on 2026-04-08:
|
|
22
|
+
|
|
23
|
+
| Slug | LOC | Recommended tier | Reasoning |
|
|
24
|
+
|----------------|------|------------------|-----------|
|
|
25
|
+
| garage | 1398 | **MONETISE** - extract first | UK-specific, wraps DVLA API, vertical. Should never have been in the public repo. |
|
|
26
|
+
| calendar | 2549 | **MONETISE** - confirmed | Recurrence + RSVP + iCal - commercial-grade, comparable to Events Calendar Pro. No live installs to break. |
|
|
27
|
+
| messages | 1762 | **MONETISE** - confirmed | Real-time 1:1/group chat is unusual for a CMS base. No live installs to break. |
|
|
28
|
+
| docs | 1506 | **MONETISE** | Document editor + version history overlaps with paid workspace products. |
|
|
29
|
+
| site-search | 1405 | **UNCERTAIN** | Borderline - keep CORE for launch; sell "SEO Pro" separately later. |
|
|
30
|
+
| theme-switcher | 717 | **UNCERTAIN** | Cosmetic, Domma-branded - keep CORE. |
|
|
31
|
+
| form-builder | 510 | **SPLIT** - confirmed | Basic form experience (field definitions, submissions, `[form]` shortcode) stays free in core. Visual drag-and-drop "Form Builder Pro" (conditional logic, multi-step, file uploads, webhooks) goes premium. Delete current stub from public repo. |
|
|
32
|
+
| blog | 2087 | **CORE** | Canonical CMS feature. |
|
|
33
|
+
| contacts | 1344 | **CORE** | Standard PIM essential. |
|
|
34
|
+
| todo | 738 | **CORE** | Lightweight essential. |
|
|
35
|
+
| notes | 616 | **CORE** | Lightweight essential. |
|
|
36
|
+
| analytics | 243 | **CORE** | Trivial page-hit counter - sell "Analytics Pro" separately. |
|
|
37
|
+
| demo-viewer | 102 | **CORE** | Marketing shortcode for Domma itself. |
|
|
38
|
+
|
|
39
|
+
**Headline finding**: ~7.2k LOC of monetisation candidates. `garage` is the most
|
|
40
|
+
urgent to extract - it's both vertical (UK) and wraps an external paid/rate-limited
|
|
41
|
+
API (DVLA).
|
|
42
|
+
|
|
43
|
+
## Recommended split
|
|
44
|
+
|
|
45
|
+
### In `domma-cms` (public repo, forever free)
|
|
46
|
+
|
|
47
|
+
- Core plugins: `blog`, `contacts`, `todo`, `notes`, `analytics`, `demo-viewer`,
|
|
48
|
+
`site-search`, `theme-switcher`
|
|
49
|
+
- **Basic forms**: form definitions, submissions, `[form slug="..."]` shortcode - the
|
|
50
|
+
primitive already exists (`content/forms/`, `server/services/forms.js`). No builder UI,
|
|
51
|
+
no drag-drop, no conditional logic.
|
|
52
|
+
- `_template/` + `scripts/create-plugin.js`
|
|
53
|
+
- The **plugin loader + lifecycle** (`server/services/plugins.js`)
|
|
54
|
+
- The **plugin installer + manager client** (code that fetches paid plugins),
|
|
55
|
+
so any licensed customer can install paid plugins without extra setup
|
|
56
|
+
|
|
57
|
+
### In `domma-cms-manager` (private repo, paid)
|
|
58
|
+
|
|
59
|
+
- Author paid plugins inside a private `plugins/` directory mirroring the same
|
|
60
|
+
shape as the public repo's `_template/`
|
|
61
|
+
- **Plugin registry** table: slug → versions → price → entitlements
|
|
62
|
+
- **Signed package builder** - bundle + sign on push
|
|
63
|
+
- **Authenticated download endpoint** - `/api/plugins/install/<slug>` that
|
|
64
|
+
returns a signed tar.gz when the caller presents a valid licence token
|
|
65
|
+
- **Signing key** - held by the manager only, hardware-backed ideally
|
|
66
|
+
|
|
67
|
+
## Architecture: installer & manager client
|
|
68
|
+
|
|
69
|
+
Two new services added to **`domma-cms`** so any installed instance can fetch
|
|
70
|
+
paid plugins once its owner has entitlements.
|
|
71
|
+
|
|
72
|
+
### `server/services/managerClient.js` - outbound HMAC client
|
|
73
|
+
|
|
74
|
+
Mirror of the inbound `managerAuth.js` shape.
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
/**
|
|
78
|
+
* Client for outbound calls from domma-cms → domma-cms-manager.
|
|
79
|
+
* Reads MANAGER_URL and INSTANCE_SECRET from env; never hard-codes the manager URL.
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
export async function registerInstance(fingerprint) {
|
|
83
|
+
// POST {MANAGER_URL}/api/instances/register
|
|
84
|
+
// Body: { fingerprint, cmsVersion, hostname }
|
|
85
|
+
// Headers: X-Instance-Token: HMAC(INSTANCE_SECRET, fingerprint)
|
|
86
|
+
// Returns: { licenseToken, instanceId }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function fetchCatalogue(licenseToken) {
|
|
90
|
+
// GET {MANAGER_URL}/api/plugins/catalogue
|
|
91
|
+
// Headers: Authorization: Bearer <licenseToken>
|
|
92
|
+
// Returns: [{ slug, version, displayName, description, price, entitled }]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function fetchPluginBundle(slug, version, licenseToken) {
|
|
96
|
+
// GET {MANAGER_URL}/api/plugins/install/<slug>/<version>
|
|
97
|
+
// Headers: Authorization: Bearer <licenseToken>
|
|
98
|
+
// Returns: { tarball: Buffer, signature: string, publicKeyId: string }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function heartbeat(licenseToken, installedSlugs) {
|
|
102
|
+
// POST {MANAGER_URL}/api/instances/heartbeat
|
|
103
|
+
// Body: { installedSlugs, versions }
|
|
104
|
+
// Used for revocation + usage analytics (opt-in)
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Environment variables** added to `.env`:
|
|
109
|
+
- `MANAGER_URL` - base URL of the manager (no trailing slash)
|
|
110
|
+
- `INSTANCE_SECRET` - 32-byte hex string generated at first run by `scripts/setup.js`
|
|
111
|
+
- Existing `MANAGER_SECRET` stays for inbound push notifications - two separate secrets
|
|
112
|
+
|
|
113
|
+
### `server/services/pluginInstaller.js` - verify + extract + lifecycle
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
/**
|
|
117
|
+
* Installs a plugin bundle fetched from the manager.
|
|
118
|
+
* Verifies the signature against a pinned public key before extracting.
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
import { verify as verifySignature } from 'crypto';
|
|
122
|
+
|
|
123
|
+
// Pinned public keys (baked into the CMS release, rotated via version bumps)
|
|
124
|
+
const TRUSTED_KEYS = {
|
|
125
|
+
'manager-2026': '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----'
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export async function installPlugin(slug, { tarball, signature, publicKeyId }) {
|
|
129
|
+
// 1. Verify signature
|
|
130
|
+
const pubKey = TRUSTED_KEYS[publicKeyId];
|
|
131
|
+
if (!pubKey) throw new Error(`Unknown public key: ${publicKeyId}`);
|
|
132
|
+
const ok = verifySignature('sha256', tarball, pubKey, Buffer.from(signature, 'base64'));
|
|
133
|
+
if (!ok) throw new Error('Plugin signature invalid - refusing to install');
|
|
134
|
+
|
|
135
|
+
// 2. Refuse path traversal - tar entries must stay under plugins/<slug>/
|
|
136
|
+
// 3. Extract to plugins/<slug>/ (reject if target already exists)
|
|
137
|
+
// 4. Validate manifest via discoverPlugins() → must load cleanly
|
|
138
|
+
// 5. Update config/plugins.json with { enabled: false, settings: {} }
|
|
139
|
+
// 6. Run onEnable lifecycle hook via runLifecycleHook(slug, 'onEnable', fastify)
|
|
140
|
+
// 7. Log install + version to instances_log.json (audit trail)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export async function uninstallPlugin(slug) {
|
|
144
|
+
// 1. Run onDisable lifecycle hook
|
|
145
|
+
// 2. Remove plugins/<slug>/ directory
|
|
146
|
+
// 3. Remove entry from config/plugins.json
|
|
147
|
+
// 4. Log uninstall
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Admin UI addition
|
|
152
|
+
|
|
153
|
+
Extend the existing `admin/js/views/plugins.js` with a **"Marketplace"** tab:
|
|
154
|
+
|
|
155
|
+
- Lists the manager catalogue via `GET /api/plugins/marketplace` (new route that
|
|
156
|
+
proxies `managerClient.fetchCatalogue()`)
|
|
157
|
+
- "Install" button on entitled plugins → `POST /api/plugins/marketplace/install`
|
|
158
|
+
which wraps `pluginInstaller.installPlugin()`
|
|
159
|
+
- "Uninstall" button on installed plugins from the manager
|
|
160
|
+
- Hides entirely if `MANAGER_URL` is unset
|
|
161
|
+
|
|
162
|
+
## Extraction workflow (for paid plugins already in public repo)
|
|
163
|
+
|
|
164
|
+
For each plugin to extract (`garage`, `docs`, and - pending Darryl's call -
|
|
165
|
+
`calendar`, `messages`):
|
|
166
|
+
|
|
167
|
+
1. **Copy the directory** into `domma-cms-manager`'s private plugins dir
|
|
168
|
+
2. **Rewrite git history in `domma-cms`**: `git filter-repo --path plugins/<slug>/ --invert-paths` on a fresh clone, force-push to a `plugins-removed` branch. This is the only git operation that requires user confirmation.
|
|
169
|
+
3. **Delete from the current tree**: `git rm -r plugins/<slug>/`
|
|
170
|
+
4. **Remove from `config/plugins.json`** if present
|
|
171
|
+
5. **Release a minor version bump** of `domma-cms` (0.11.x → 0.12.0) noting
|
|
172
|
+
the plugin removal in the CHANGELOG
|
|
173
|
+
6. **Verify**: run `npm run build` + existing Calendar/Messages manual test
|
|
174
|
+
smoke check; check that no core code references the removed plugin slug
|
|
175
|
+
|
|
176
|
+
**Important**: step 2 is history rewriting and will require a co-ordinated
|
|
177
|
+
force-push. Do not run it without explicit confirmation. Until then, the
|
|
178
|
+
source of extracted plugins remains visible in git history even after removal
|
|
179
|
+
from `HEAD` - treat the extraction as mitigation, not cure.
|
|
180
|
+
|
|
181
|
+
## Critical files
|
|
182
|
+
|
|
183
|
+
**Create (in `domma-cms`):**
|
|
184
|
+
- `server/services/managerClient.js` - outbound HMAC client
|
|
185
|
+
- `server/services/pluginInstaller.js` - verify + extract + lifecycle
|
|
186
|
+
- `server/routes/api/plugin-marketplace.js` - `/api/plugins/marketplace` routes
|
|
187
|
+
- `admin/js/views/plugin-marketplace.js` - Marketplace tab view
|
|
188
|
+
- `scripts/gen-instance-secret.js` - generates `INSTANCE_SECRET` on first setup
|
|
189
|
+
|
|
190
|
+
**Edit (in `domma-cms`):**
|
|
191
|
+
- `scripts/setup.js` - generate `INSTANCE_SECRET` during setup
|
|
192
|
+
- `admin/js/views/plugins.js` - wire in Marketplace tab
|
|
193
|
+
- `server/server.js` - register `/api/plugins/marketplace` routes
|
|
194
|
+
- `.env.example` - document `MANAGER_URL`, `INSTANCE_SECRET`
|
|
195
|
+
- `config/plugins.json` - extracted plugins removed
|
|
196
|
+
|
|
197
|
+
**Create (in `domma-cms-manager`):**
|
|
198
|
+
- Private `plugins/` directory mirroring the `_template/` shape
|
|
199
|
+
- Build pipeline: test → minify → tar.gz → sign → upload to blob store
|
|
200
|
+
- `/api/instances/register`, `/api/instances/heartbeat` routes
|
|
201
|
+
- `/api/plugins/catalogue`, `/api/plugins/install/:slug/:version` routes
|
|
202
|
+
- Customer entitlements table (schema TBD in manager's own plan)
|
|
203
|
+
|
|
204
|
+
## Decisions (all confirmed 2026-04-08)
|
|
205
|
+
|
|
206
|
+
1. ✅ **Calendar** - **MONETISE**. No live installs to break.
|
|
207
|
+
2. ✅ **Messages** - **MONETISE**. No live installs to break.
|
|
208
|
+
3. ✅ **`form-builder` stub** - **SPLIT**. Basic form experience (definitions, submissions,
|
|
209
|
+
`[form]` shortcode) stays free. Visual drag-and-drop "Form Builder Pro" goes premium
|
|
210
|
+
in manager. Delete the current stub from the public repo.
|
|
211
|
+
4. ✅ **Public key rotation** - pinned-by-version for v1.
|
|
212
|
+
5. ✅ **Entitlement cache TTL** - 30 days offline.
|
|
213
|
+
6. ✅ **Telemetry / heartbeat** - opt-in, disabled by default.
|
|
214
|
+
|
|
215
|
+
## Verification
|
|
216
|
+
|
|
217
|
+
After installer plumbing lands in `domma-cms`:
|
|
218
|
+
|
|
219
|
+
1. Unset `MANAGER_URL` → Marketplace tab hidden, rest of admin unaffected.
|
|
220
|
+
2. Set `MANAGER_URL` to a stub server returning fixture data → Marketplace tab
|
|
221
|
+
shows fixture plugins.
|
|
222
|
+
3. Install a test plugin via stub - verify signature rejection path: tamper with
|
|
223
|
+
the tarball by one byte and confirm install fails loudly.
|
|
224
|
+
4. Install a test plugin with valid signature - verify `plugins/<slug>/` appears,
|
|
225
|
+
`config/plugins.json` updated, `onEnable` hook ran.
|
|
226
|
+
5. Uninstall - verify directory removed, `onDisable` ran, `config/plugins.json`
|
|
227
|
+
cleaned up.
|
|
228
|
+
6. Existing core plugins (`blog`, `notes`, etc.) remain unaffected throughout.
|
|
229
|
+
|
|
230
|
+
After extraction of paid plugins from public repo:
|
|
231
|
+
|
|
232
|
+
7. `git log -- plugins/garage/` returns nothing after history rewrite.
|
|
233
|
+
8. Fresh clone of public repo has no `plugins/garage/` directory.
|
|
234
|
+
9. `_publish/` build succeeds with no references to extracted plugins.
|
|
235
|
+
|
|
236
|
+
## Out of scope for this plan
|
|
237
|
+
|
|
238
|
+
- **Manager-side implementation** - the private repo has its own planning track
|
|
239
|
+
- **Payment processing** - Stripe integration, invoicing, dunning etc. all live in manager
|
|
240
|
+
- **Customer dashboard for manager** - manager's own admin UI
|
|
241
|
+
- **Auto-update of installed paid plugins** - v1 = manual click, auto-update is v2
|
|
242
|
+
- **Rewriting existing inbound `managerAuth.js`** - stays as-is, it's orthogonal
|