Skip to content

Security

Who holds what

Secret Lives in Who uses it
Warehouse credentials praxis.db (deployment row), and the semantic compose file Cube only
CUBEJS_API_SECRET praxis.db, and the semantic compose file the model store, to sign Cube JWTs. Never leaves that compose file at run time
Model store token praxis.db, and the semantic compose file the portal, to call the store
Sandbox token praxis.db, and the sandbox compose file the portal, to call the sandbox
Portal token memory only, new each start your browser
MCP token praxis.db external agents calling /mcp

The three deployment secrets are minted with secrets.token_urlsafe when you first connect, and leave the portal only inside the compose files you download.

The database file

~/.praxis/praxis.db holds the warehouse credentials as plaintext JSON. The portal sets it to mode 600 (readable only by you) every time it starts. Keep DATA_DIR on a disk you trust, and treat a copy of the file as a copy of the password.

GET /api/onboarding/deployment/{service}/compose is the only route that returns credential values, and it answers as a download (Content-Disposition: attachment).

What the agents cannot do

  • No agent writes SQL. Every query is Cube JSON and passes the query gate; only joins and measures the model defines can be used.
  • The sandbox holds no credential. It cannot sign a Cube token and has no warehouse password, so the Python the agent runs there can only see rows the gate already let through.
  • Script approval (APPROVE_SCRIPTS) shows each chat script before it runs. In a Flow, an unchanged prepared script runs without approval because it was reviewed when it was saved; any other script asks.
  • The question chat cannot start a Flow run, and no agent can refresh a dashboard. Both are buttons, so an instruction like "tidy up this board" cannot turn into a dozen warehouse queries.

What is exposed on the network

Every published port binds to 127.0.0.1 by default: the portal (8420), the model store (8000) and the sandbox (8600). Cube's port is not published at all. To expose a service beyond the machine, change the left-hand side of its compose ports: line deliberately — and note that the sandbox can reach the network, which is why its token is mandatory.

MCP

/mcp has its own Bearer token, separate from the portal token, and it survives restarts. When MCP is switched off, /mcp answers 404. Rotate on the Agents page mints a new token and breaks every pasted client configuration. MCP tools are read-only: search the model, describe it, and run a gated query capped at MAX_ROWS.