Licensing and editions
Licence
Solvo is licensed per domain. Keys are sold on MoJamoza Systems (systems.mojamoza.com) for the
solvo product and start with MJB-. The check works exactly like Creator Collective's and Family OS's.
- Activating: enter the key in the installer (last step), or later under Super Admin → System &
licence → Activate. Activation binds the key to this domain (the host in
APP_BASE_URL, or the address you're browsing on). - Checks: the result is cached and re-verified every 12 hours on a page load (15 minutes after a
network blip), plus daily by
scripts/verify_license.php. Replies are signed (HMAC-SHA256) and checked against the secret inconfig/license-server.php; both reply formats the store uses are accepted. - Grace period: once a key has been activated, Solvo keeps working through three failed checks in a row if the licence server can't be reached. An invalid or revoked key, or a key active on another domain, pauses the platform at once.
- While paused: Super Admins are taken to System & licence with the reason; everyone else sees a
calm "We'll be back shortly" page; APIs answer
503 license_inactive. Sign-in, password reset, the licence page and the M-Pesa / Paystack / partner callbacks always keep working, so a pause can always be fixed and no payment is lost. Command-line scripts (cron) are never paused. - System & licence shows the status, masked key, domain, server, product, a fingerprint of the signing secret, last check, activation date and failed checks — and, when something is wrong, what the server said plus Technical details for MoJamoza support (address, HTTP status, signature received/expected, the raw reply).
- "Secret mismatch" means this copy's
config/license-server.phpdoesn't carry the secret systems.mojamoza.com signs with. Upload that file from the latest package. - Moving domains: ask MoJamoza support to transfer the key.
config/license-server.php ships with the package and is replaced on every update:
return [
'server' => 'https://systems.mojamoza.com/license-api',
'secret' => '…', // set by MoJamoza before packaging
'product' => 'solvo', // Solvo's slug on systems.mojamoza.com
];
1.x SYNC_ENDPOINT / SYNC_SECRET in .env are ignored (a 1.x SYNC_KEY is still picked up). For
testing only, LICENSE_SERVER_OVERRIDE + LICENSE_SECRET_OVERRIDE in .env replace the server and
secret.
Editions
The sale and demo packages contain the same code. config/edition.php says which one a copy is:
<?php return ['edition' => 'standard']; // or 'demo'
DEMO_MODE=true in .env also switches a copy into the demo edition (as in 1.x).
What the demo edition changes
- No licence check.
- The login page shows one-click sign-in buttons for every role (all use the password
Demo@2026). - Email and SMS are never sent. Every message is still rendered and logged with the status
suppressed, so visitors can open the Message log and see exactly what would have gone out. - Read-only: email/SMS engines, licence, appearance defaults, payment keys, schools connecting their own engines, password or email changes on the demo accounts, and suspending or cancelling the demo schools. Visitors see a short note explaining why.
- A thin "Demo" strip across the top of every dashboard.
Running the public demo
- Install the demo package like any other copy (installer, sample data not needed — the reset adds it).
- Add the nightly reset cron job (it's listed under System & licence on the demo):
0 0 * * * /usr/local/bin/php /home/USER/solvo/scripts/demo_reset.php >/dev/null 2>&1
- Run it once by hand to load everything now:
php scripts/demo_reset.php.
The reset drops every table in the configured database, rebuilds the schema, loads the two demo
schools (Riverside Academy and Greenfield Primary) with students, fees, results, timetables, library,
transport, payroll, websites, live chat conversations and a populated message log, creates the demo
Super Admin (superadmin@solvo.demo) and copies the demo logos into storage. It refuses to run on a
standard edition unless given --force, because it wipes the database.