Live operator console
Open https://asi-database-node-api.arybit.co.ke/ or /admin/. The console polls actual /health, /ready, and /version responses every 15 seconds. No sample operational data is displayed. Documentation and All pages navigation remain available without authentication.
Connect
Retrieve the private VM operator token over your trusted SSH connection:
sudo cat /opt/asi-database-node-api/shared/setup-token
Enter it in the console's Operator connection form. The token stays in browser memory, is never written to browser storage, and is cleared on disconnect or navigation. Treat it as an administrator credential: it authorizes database queries, deployment changes and credential initialization. Disconnect clears the browser credential; it does not revoke copied tokens. To rotate, replace the VM token file with a newly generated secret through SSH, keeping mode 0600. Every subsequent operator request reads the current token file.
The console requires HTTPS, except for local development at localhost/127.0.0.1. The VM service rejects console requests forwarded over plain HTTP. DNS setup remains separately available at /ui/dns.html during first installation.
Database and service operations
- Browse actual information_schema tables and populate a bounded SELECT preview.
- Execute one SQL statement with the configured application database role. PostgreSQL uses extended query protocol; MySQL multi-statements are disabled by the driver. Read-only mode uses a read-only transaction and rolls back. MySQL read-only statements must begin with SELECT.
- Enable committed writes and type
EXECUTE SQLfor each write. Permissions, RLS, constraints and triggers still apply. MySQL DDL can commit implicitly, so it does not have PostgreSQL transactional rollback guarantees. - Inspect the deployed migration manifest, deployment phases, source revision and service journal.
- Apply enabled pending migrations using the existing checksummed runner. Disabled legacy MySQL migrations remain blocked. Production migrations require an encrypted backup less than 24 hours old.
- Create encrypted backups with a separate backup identity and age recipient.
- Restore a selected encrypted backup into an empty isolated
asi_restore_*database. Active application databases are excluded by the restore tool. A successful restore populates the isolated target; a repeated restore requires a newly prepared empty target. Active-database replacement remains an operator procedure outside this console. - Restart and verify the API, verify public HTTPS, or roll back to a retained previous release. Rollback does not reverse database migrations.
Result sets are limited to 200 rows and 200 KB; each displayed value is limited to 2000 characters. PostgreSQL statements have a five-second statement timeout and two-second lock timeout. MySQL/MariaDB enforce their supported execution timeout plus driver I/O deadlines. The worker has a 12-second process deadline. A request interrupted during a write may have committed: inspect the database before retrying. Polling and sign-out do not cancel jobs already started on the server.
Initialize operation credentials
For managed local PostgreSQL, click Initialize operation credentials and type INITIALIZE. This does not run application schema migrations. It creates protected files in /opt/asi-database-node-api/shared/:
| File | Purpose |
|---|---|
backup.env |
Separate backup reader, with SELECT grants on application schemas and BYPASSRLS for complete forced-RLS dumps |
migration.env |
Dedicated migration login inheriting the application database owner's permissions |
restore.env |
Unprivileged identity for a separate empty test database |
restore-identity.agekey |
Private age recovery key, mode 0600 |
console-config.json |
Deployment owner, backup recipient and protected backup environment path |
Existing managed credentials are retained. Unrelated operation credentials require manual review. Backup grants refresh after successful console migrations. Initialization for MySQL or externally managed databases requires manually provisioned identities and protected configuration.
Copy encrypted backups, checksums, and the private age identity to separately secured off-VM storage through a trusted channel. Keeping the recovery key only beside the backups does not provide disaster recovery. The UI lists encrypted backups; it does not expose or download private key material.
Operator API
Nginx forwards /setup-api/console/ to the loopback operator service on port 8090. All endpoints require Authorization: Bearer <operator-token>. Cross-origin browser requests are rejected. POST requests require Content-Type: application/json; bodies are limited to 32 KB. Errors omit driver credentials and SQL values.
| Method | Path suffix | Behavior |
|---|---|---|
| GET | state |
Actual active deployment, database identity, manifests, backups, prerequisite flags |
| GET | logs |
Last 150 lines of the active API journal, redacted |
| GET | job |
Current lifecycle job, exit status, bounded redacted output |
| POST | tables |
{} returns accessible table metadata |
| POST | query |
{"sql":"SELECT 1","write":false} returns columns and rows |
| POST | query |
Writes additionally require "write":true,"confirm":"EXECUTE SQL" |
| POST | initialize, backup, migrate, recover, rollback, verify |
Require {"confirm":"<UPPERCASE ACTION>"} |
| POST | restore |
Requires {"confirm":"RESTORE","backup":"<listed filename.tar.age>"} |
SQL and lifecycle operations share the operator lock. They also coordinate with the deployment lock. Job status is held in service memory; a service restart clears the displayed job status. Operation outcomes are appended to protected console-audit.jsonl without SQL, tokens or result rows. Diagnose interruptions through the VM service journal and deployment logs before retrying mutations. There is no arbitrary OS command endpoint.
Verification
python -m unittest discover -s tests -v
python -m pytest backend/tests -q
node --check ui/js/Console.js
The SQL integration tests require an explicitly isolated PostgreSQL server; set TEST_CONSOLE_POSTGRES_PORT to its loopback port. They create and remove their own test database and role. Never point this variable at a production database.