OPS-004
A read-only admin mode over real data
Show a live panel to a buyer, an investor or a prospective moderator without letting them change anything, and without inventing fake data.
Demo data is a trap. It has to be maintained, it never looks quite real, and it teaches whoever is watching nothing about how the site actually behaves. The alternative is to show the real panel with every write turned off.
The pattern is one flag and one guard function called at the top of every handler that changes something. Because the guard is a single function, adding a new admin page cannot accidentally bypass it — it will simply not be protected until you add the one line, which is the sort of omission a review catches.
The second half is masking. Real data means real email addresses and real payout wallets, and neither belongs on a screen you are sharing. Mask them at display time rather than at query time, so the panel still sorts and searches correctly.
function demo_mode(): bool
{
return setting_bool('demo_mode');
}
/** First line of every handler that writes. */
function demo_guard(): void
{
if (demo_mode()) {
http_response_code(403);
exit('Read-only mode is on. Turn it off in Settings to make changes.');
}
}
function mask_email(string $email): string
{
if (!demo_mode() || $email === '') {
return $email;
}
[$user, $domain] = array_pad(explode('@', $email, 2), 2, '');
return substr($user, 0, 2) . str_repeat('*', max(3, strlen($user) - 2)) . '@' . $domain;
}
function mask_wallet(string $address): string
{
if (!demo_mode() || strlen($address) < 12) {
return $address;
}
return substr($address, 0, 5) . '…' . substr($address, -4);
}
function mask_name(string $name): string
{
return demo_mode() ? substr($name, 0, 1) . str_repeat('*', max(3, strlen($name) - 1)) : $name;
}
Using it
Show a persistent strip across the top while the mode is on. Someone will forget it is enabled and then report that saving is broken.
Make the setting that disables the mode the one write the guard permits, or you will lock yourself out of your own panel.
Mask anything that identifies a person or moves money: addresses, emails, wallets, API keys, transaction ids.
What bites people
Read-only is not a permission system. Anyone who can see the panel can still read everything, so this is for someone standing next to you, not for handing out access.
Guard the handler, not the button. Hiding a form does nothing about a POST sent directly.