{"id":"69ecef9b60bb8b34fce600b1","title":"Root Operator Tasks","path":"how-to/technical-articles/2026-04-21-using-ramblers-salesforce-mock/root-operator-tasks","contentMarkdown":"# 21-Apr-2026 — Root operator tasks\n\n_____\n\nThe root operator is the only account that can provision other operators. Everything else (creating tenants, generating tokens, loading data, calling the API) is identical to a normal operator account — root simply has the additional ability to add and list operators.\n\nIf you're not the root operator, you can skip this page.\n\n[← Back to the overview](https://ngx-ramblers.org.uk/how-to/technical-articles/2026-04-21-using-ramblers-salesforce-mock)\n\n![](https://ngx-ramblers.org.uk/api/aws/s3/site-content/126ac490-303e-4f72-bd2c-e1dbeb5d9faa.png)\n\n*The root-only Operators panel — create a new operator with username, password (or hit Generate for a strong random one), and label. The table below lists all existing operators with their roles and last-login times.*\n\n## Operators panel\n\nSign in as root and a panel labelled **Operators** appears at the top of the dashboard, marked with a `root only` chip. It is collapsed by default — hit **Show** to expand.\n\nInside:\n\n- A form with **Username**, **Password**, and **Label** fields\n- A **Generate** button next to the password field that fills it with a strong random string (12+ characters, mixed case, digits, symbols)\n- After successful creation, a reveal panel shows the password back with a **Copy** button (the only time it's shown in plaintext — see warning below)\n- A table of all existing operators: username, label, role (`root` or `operator`), created timestamp, last login\n\n### Create an operator\n\n1. Type a **Username** (3 to 40 characters, lowercase). Convention: dot-separated like `charlie.bigley` or `firstname.surname`.\n2. Type a **Password** (12 to 100 characters), or hit **Generate** for a strong random one.\n3. Optional **Label** — human-readable, shown in the operators table to remind you who it's for (e.g. `Charlie Bigley / MailMan`).\n4. Hit **Create operator**. The reveal panel shows the password with a Copy button.\n5. Send the username and password to the new operator privately — by email, encrypted chat, or whatever secure channel you'd normally use. **Not** through the mock server itself.\n\nThe reveal panel is the only point at which the password is visible in plaintext to anyone — including you. The server stores only a bcrypt hash, so if the new operator loses the password before they sign in, the only recovery path is to provision a new operator (or, in extremis, redeploy with a new `ADMIN_PASSWORD` to rotate the root password).\n\n### List existing operators\n\nThe table below the form shows everyone, in reverse-chronological order of creation. The root operator appears with role `root`; everyone else is `operator`. Last-login timestamps make it easy to spot accounts that were provisioned but never used.\n\nThere is no UI for revoking, suspending, or deleting an operator at the moment — if that's needed, raise an issue or do it directly against MongoDB.\n\n## API endpoints\n\nThe same operations are available over the admin API for scripting. Both require an authenticated root session (cookie from `/admin/api/login`).\n\n```sh\n# 1. Sign in as root, save the session cookie\ncurl -sS -c /tmp/rsm.jar \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"username\":\"admin\",\"password\":\"YOUR-ROOT-PASSWORD\"}' \\\n  https://salesforce-mock.ngx-ramblers.org.uk/admin/api/login\n\n# 2. Create an operator\ncurl -sS -b /tmp/rsm.jar \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"username\": \"charlie.bigley\",\n    \"password\": \"a-strong-one-12-chars-or-more\",\n    \"label\": \"Charlie Bigley / MailMan\"\n  }' \\\n  https://salesforce-mock.ngx-ramblers.org.uk/admin/api/operators\n\n# 3. List operators\ncurl -sS -b /tmp/rsm.jar \\\n  https://salesforce-mock.ngx-ramblers.org.uk/admin/api/operators\n\nrm /tmp/rsm.jar\n```\n\n## Bootstrapping a fresh deployment\n\nWhen the mock is deployed to a brand-new MongoDB, no operators exist. The deploy reads two environment variables to seed:\n\n| Variable | Used for |\n|---|---|\n| `ADMIN_USERNAME` | The root operator's username (default `admin`) |\n| `ADMIN_PASSWORD` | The root operator's initial password |\n| `BOOTSTRAP_TOKEN` | A long random string. If set, enables the **Bootstrap token** sign-in tab, which signs you in as the root operator without needing the password. |\n\nIf you set `ADMIN_PASSWORD` and later change it on the running deploy, the next process restart re-hashes and updates the stored hash. That's how root password rotation works — there's no in-app rotation flow.\n\nOnce the bootstrap is done and at least one real operator exists, unset `BOOTSTRAP_TOKEN` from the deployment so the bootstrap tab can no longer be used.\n\n## Back to the overview\n\n[**Overview →**](https://ngx-ramblers.org.uk/how-to/technical-articles/2026-04-21-using-ramblers-salesforce-mock)","contentHtml":"<h1>21-Apr-2026 — Root operator tasks</h1>\n<hr>\n<p>The root operator is the only account that can provision other operators. Everything else (creating tenants, generating tokens, loading data, calling the API) is identical to a normal operator account — root simply has the additional ability to add and list operators.</p>\n<p>If you&#39;re not the root operator, you can skip this page.</p>\n<p><a href=\"https://ngx-ramblers.org.uk/how-to/technical-articles/2026-04-21-using-ramblers-salesforce-mock\">← Back to the overview</a></p>\n<p><img src=\"https://ngx-ramblers.org.uk/api/aws/s3/site-content/126ac490-303e-4f72-bd2c-e1dbeb5d9faa.png\" alt=\"\"></p>\n<p><em>The root-only Operators panel — create a new operator with username, password (or hit Generate for a strong random one), and label. The table below lists all existing operators with their roles and last-login times.</em></p>\n<h2>Operators panel</h2>\n<p>Sign in as root and a panel labelled <strong>Operators</strong> appears at the top of the dashboard, marked with a <code>root only</code> chip. It is collapsed by default — hit <strong>Show</strong> to expand.</p>\n<p>Inside:</p>\n<ul>\n<li>A form with <strong>Username</strong>, <strong>Password</strong>, and <strong>Label</strong> fields</li>\n<li>A <strong>Generate</strong> button next to the password field that fills it with a strong random string (12+ characters, mixed case, digits, symbols)</li>\n<li>After successful creation, a reveal panel shows the password back with a <strong>Copy</strong> button (the only time it&#39;s shown in plaintext — see warning below)</li>\n<li>A table of all existing operators: username, label, role (<code>root</code> or <code>operator</code>), created timestamp, last login</li>\n</ul>\n<h3>Create an operator</h3>\n<ol>\n<li>Type a <strong>Username</strong> (3 to 40 characters, lowercase). Convention: dot-separated like <code>charlie.bigley</code> or <code>firstname.surname</code>.</li>\n<li>Type a <strong>Password</strong> (12 to 100 characters), or hit <strong>Generate</strong> for a strong random one.</li>\n<li>Optional <strong>Label</strong> — human-readable, shown in the operators table to remind you who it&#39;s for (e.g. <code>Charlie Bigley / MailMan</code>).</li>\n<li>Hit <strong>Create operator</strong>. The reveal panel shows the password with a Copy button.</li>\n<li>Send the username and password to the new operator privately — by email, encrypted chat, or whatever secure channel you&#39;d normally use. <strong>Not</strong> through the mock server itself.</li>\n</ol>\n<p>The reveal panel is the only point at which the password is visible in plaintext to anyone — including you. The server stores only a bcrypt hash, so if the new operator loses the password before they sign in, the only recovery path is to provision a new operator (or, in extremis, redeploy with a new <code>ADMIN_PASSWORD</code> to rotate the root password).</p>\n<h3>List existing operators</h3>\n<p>The table below the form shows everyone, in reverse-chronological order of creation. The root operator appears with role <code>root</code>; everyone else is <code>operator</code>. Last-login timestamps make it easy to spot accounts that were provisioned but never used.</p>\n<p>There is no UI for revoking, suspending, or deleting an operator at the moment — if that&#39;s needed, raise an issue or do it directly against MongoDB.</p>\n<h2>API endpoints</h2>\n<p>The same operations are available over the admin API for scripting. Both require an authenticated root session (cookie from <code>/admin/api/login</code>).</p>\n<pre><code class=\"language-sh\"># 1. Sign in as root, save the session cookie\ncurl -sS -c /tmp/rsm.jar \\\n  -H &#39;Content-Type: application/json&#39; \\\n  -d &#39;{&quot;username&quot;:&quot;admin&quot;,&quot;password&quot;:&quot;YOUR-ROOT-PASSWORD&quot;}&#39; \\\n  https://salesforce-mock.ngx-ramblers.org.uk/admin/api/login\n\n# 2. Create an operator\ncurl -sS -b /tmp/rsm.jar \\\n  -H &#39;Content-Type: application/json&#39; \\\n  -d &#39;{\n    &quot;username&quot;: &quot;charlie.bigley&quot;,\n    &quot;password&quot;: &quot;a-strong-one-12-chars-or-more&quot;,\n    &quot;label&quot;: &quot;Charlie Bigley / MailMan&quot;\n  }&#39; \\\n  https://salesforce-mock.ngx-ramblers.org.uk/admin/api/operators\n\n# 3. List operators\ncurl -sS -b /tmp/rsm.jar \\\n  https://salesforce-mock.ngx-ramblers.org.uk/admin/api/operators\n\nrm /tmp/rsm.jar\n</code></pre>\n<h2>Bootstrapping a fresh deployment</h2>\n<p>When the mock is deployed to a brand-new MongoDB, no operators exist. The deploy reads two environment variables to seed:</p>\n<table>\n<thead>\n<tr>\n<th>Variable</th>\n<th>Used for</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>ADMIN_USERNAME</code></td>\n<td>The root operator&#39;s username (default <code>admin</code>)</td>\n</tr>\n<tr>\n<td><code>ADMIN_PASSWORD</code></td>\n<td>The root operator&#39;s initial password</td>\n</tr>\n<tr>\n<td><code>BOOTSTRAP_TOKEN</code></td>\n<td>A long random string. If set, enables the <strong>Bootstrap token</strong> sign-in tab, which signs you in as the root operator without needing the password.</td>\n</tr>\n</tbody></table>\n<p>If you set <code>ADMIN_PASSWORD</code> and later change it on the running deploy, the next process restart re-hashes and updates the stored hash. That&#39;s how root password rotation works — there&#39;s no in-app rotation flow.</p>\n<p>Once the bootstrap is done and at least one real operator exists, unset <code>BOOTSTRAP_TOKEN</code> from the deployment so the bootstrap tab can no longer be used.</p>\n<h2>Back to the overview</h2>\n<p><a href=\"https://ngx-ramblers.org.uk/how-to/technical-articles/2026-04-21-using-ramblers-salesforce-mock\"><strong>Overview →</strong></a></p>\n"}