Setup & configuration

Keys, profiles and the rules that keep them safe

Everything dlake does is tied to a tenant and an API key. This page explains how you get a key, how profiles keep tenants apart, why scoped keys need a restart, and which environment variables and argument forms the CLI understands.

How do I get a key?

In plain wordsA key is the password an app or a person uses with dlake. Your first one arrives when your Data Lake is created; after that you make more, each for a specific purpose.

1. The bootstrap key

When dlake register status --watch sees your Data Lake seeded, it prints a once-only, 7-day owner-admin key and saves it into a profile. Copy it; it is never shown again. It drives both the data plane and the admin control plane immediately.

2. Longer-lived keys

Mint them from the terminal or from the console under Settings → API Keys. dlake keys create mints an unscoped (full-access) key and prints it once. dlake admin create_api_key mints a scoped key limited to entities and actions (see below). Keys can be extended, revoked and restored; revocation takes effect immediately.

3. The welcome email

A second email carries the tenant owner's temporary password for the web console. Log in and change it. Those two emails are the whole human journey.

$ dlake keys create --name ci-reader --expires-days 90 --profile acme
dlk_...   (shown once - store it now)
$ dlake keys list --profile acme
$ dlake keys revoke <id> --profile acme

Profiles: one per tenant

A profile stores the tenant slug, the key and a cached token. Since 0.5.7 there is no default profile: you name the tenant on every command with --profile, or set DLAKE_PROFILE once per shell session. The reason is safety: before that change a command could silently run against the wrong customer.

Give the key through DLAKE_API_KEY or --api-key-stdin. A plain --api-key flag still works but leaks to shell history and the process table.

$ DLAKE_API_KEY=dlk_... dlake login --domain acme --profile acme
$ dlake profiles list
$ export DLAKE_PROFILE=acme
$ dlake status
$ dlake logout --profile acme

Scoped keys: least privilege for apps and agents

In plain wordsA scoped key can only touch the tables and actions you list. The limit is enforced inside the database, so it holds even if the app is compromised.

A scope entry names an entity and one or more action booleans: canRead, canCreate, canUpdate, canDelete, canExecute, plus an optional schemaName for an external schema. REST PATCH/PUT by key need both canCreate and canUpdate. A scoped key cannot drive the admin control plane, and raw SQL is refused for it unless the key carries the AllowRawSql opt-in.

[
  { "entityName": "pizza_menu_items", "canRead": true },
  { "entityName": "usp_PlaceOrder",   "canExecute": true }
]
$ dlake admin create_api_key --keyName pizza-web --expirationDays 180 --scope @scope.json
$ dlake admin restart_dab --confirm true

Roles

Tenant users hold Admin (everything), User (data read/write plus viewing schema objects) or ReadOnly. The sync-product command groups (CRMPro, Normal Sync, ODBC and API sync) require a key that belongs to an Admin user; otherwise the command says so and exits 3 without changing anything. Never ship a key to a browser: keep it in a small server-side proxy.

The canonical build sequence

In plain wordsCreate the tables, tell the API to serve them, restart it, load data, make a key for your app, restart again. The order matters.

# 1. authenticate with a FULL-SCOPE admin key
$ dlake login --domain acme --profile acme
$ dlake tool get_active_schema --profile acme
# 2. define schema (operates on the ACTIVE schema, usually DLO)
$ dlake admin create_table --tableName pizza_menu_items --columns @menu_items.json --primaryKey Sku
$ dlake admin create_procedure --procedureName usp_PlaceOrder --parameters @params.json --body @proc.sql
# 3. expose, then apply with a restart
$ dlake admin set_entity_exposure --entity pizza_menu_items --expose true
$ dlake admin set_entity_exposure --entity usp_PlaceOrder --expose true
$ dlake admin restart_dab --confirm true
# 4. now the data plane can see them
$ dlake tool create_record --entity pizza_menu_items ...
# 5. least-privilege key for the app, then restart again
$ dlake admin create_api_key --keyName pizza-web --expirationDays 180 --scope @scope.json
$ dlake admin restart_dab --confirm true

Things that bite on the way through

  • The data plane sees only exposed entities. A table that exists but is not exposed and published returns EntityNotFound. Raw SQL reads do not need exposure.
  • The active schema is read-only from the CLI. Read it with get_active_schema; it is switched only from the console's schema dropdown. Qualify raw SQL (FROM DLO.table) and prefix object names per app.
  • Stored-procedure parameter names start with @, the type key is dataType, and reserved T-SQL words (LineNo, Key, Order, User) fail as column names.
  • Data API writes are not transactional. Put multi-row writes in a stored procedure with BEGIN TRAN/COMMIT, expose it, and call it as one POST.
  • ingest_table needs a natural-key primary key; seed identity-keyed tables with create_record.

The dlake agent skill encodes all of this for coding agents.

Environment variables and flags

VariablePurpose
DLAKE_PROFILEName the tenant profile once per shell session instead of passing --profile on every command.
DLAKE_API_KEYSupply the API key to dlake login without putting it on the command line.
DLAKE_DOWNLOAD_BASEBinary mirror base for npm installs (default: the Commercient download host).
DLAKE_VERSIONPin a specific binary version at npm install time (same or newer only).
DLAKE_SHA256Operator-pinned expected digest (64 hex) for air-gapped installs.
DLAKE_ALLOW_MIRROR_CHECKSUMSTake SHA256SUMS from the mirror too (off by default; unsafe, prints a warning).
DLAKE_ALLOW_DOWNGRADEPermit an older DLAKE_VERSION than the installed package (off by default).
DLAKE_S3_ACCESS_KEY_ID / DLAKE_S3_SECRET_ACCESS_KEYCredentials for dlake s3 connections add, instead of interactive prompts or --*-stdin.
--config-dir <dir>Global flag: where profiles and cached tokens live.

Global flags on every command: --json, --profile <name>, --config-dir <dir>. Login accepts per-profile --auth-url, --api-url and --mcp-url overrides.

Argument forms

  • Scalars: --tableName Invoice, --confirm true.
  • Arrays and objects: a value starting with [ or { is sent as JSON; a plain comma list still works for arrays of scalars. Malformed JSON is reported as a usage error naming the argument.
  • @file: read the value from a file, for any argument. The reliable form on Windows. @@ escapes a literal leading @.

Exit codes

0Success
1Error
2Usage error (bad flag or argument)
3Permission or authentication denied

Health checks in dlake status send no credential and judge each host on its own, so one blocked service never masks another.