Skip to content

Commit 34893fa

Browse files
authored
cleanup(basilica): remove dashboard runtime-key injection (closes #245) (#247)
The `_inject_runtime_key_into_dashboard()` helper and the README's "Dashboard wiring follow-up" caveat promised that `LLMTRACE_AUTH_RUNTIME_KEY` would be consumed by a future dashboard change. Post-merge investigation showed the dashboard only calls the proxy's `/api/v1/*` admin endpoints (`dashboard/src/lib/api.ts`, `dashboard/src/lib/proxy-helpers.ts`); no code path consumes the operator key. The injection was dead weight and the note misled future contributors. Changes: - `lifecycle.py`: delete `_inject_runtime_key_into_dashboard()` and its call site in `provision()`; update docstrings to describe the actual two-tier model (admin key in dashboard env; operator key returned in `TenantInstances.api_key` for the tenant's external apps). - `README.md`: rewrite the bootstrap step 6 and drop the "Dashboard wiring follow-up" caveat. - `configs/examples/starter.yaml`: update the dashboard env comment. - `tests/test_operator_key_minting.py`: replace the positive runtime-key assertion with a negative one (`LLMTRACE_AUTH_RUNTIME_KEY not in dash_create["env"]`) and convert the helper-injection test into an absence guard (`not hasattr(lifecycle, "_inject_runtime_key_into_dashboard")`) so the contract is locked in. Net deletion: dead code + misleading docs gone. All other lifecycle behaviour (operator key minted and returned, admin key returned, tenant bootstrap) is untouched.
1 parent 14ab366 commit 34893fa

4 files changed

Lines changed: 32 additions & 47 deletions

File tree

deployments/basilica/README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,13 @@ issues TWO keys with distinct scopes:
334334
5. Calls `POST /api/v1/auth/keys` (auth: admin key, scoped to that
335335
tenant UUID) with body `{name: "tenant-runtime", role: "operator",
336336
tenant_id: <uuid>}` and captures the plaintext operator key.
337-
6. Adds `LLMTRACE_AUTH_RUNTIME_KEY=<operator_key>` to the dashboard env
338-
(informational today; consumed by a follow-up dashboard wiring
339-
change) and creates the dashboard deployment.
337+
6. Creates the dashboard deployment. The dashboard env carries the
338+
admin key (its only consumer today is the proxy's `/api/v1/*` admin
339+
endpoints — see `dashboard/src/lib/api.ts`,
340+
`dashboard/src/lib/proxy-helpers.ts`). The operator key is **not**
341+
injected into the dashboard env because no dashboard code path
342+
consumes it; it is returned to the caller for the tenant's external
343+
apps to use against `/v1/*` runtime traffic.
340344
7. Returns `TenantInstances(api_key=<operator>, admin_key=<admin>)`.
341345

342346
Both plaintext keys are exposed only at this moment. Persist them
@@ -418,12 +422,6 @@ without any control-plane scope. See
418422

419423
### Caveats and follow-ups
420424

421-
- **Dashboard wiring follow-up**: the Next.js dashboard
422-
(`dashboard/src/lib/api.ts`, `dashboard/src/lib/proxy-helpers.ts`)
423-
currently only reads `LLMTRACE_AUTH_ADMIN_KEY`. The lifecycle layer
424-
injects `LLMTRACE_AUTH_RUNTIME_KEY` informationally; a separate PR
425-
should switch the dashboard to use the runtime key for tenant-facing
426-
traffic and the admin key only for admin pages.
427425
- **Admin key rotation** is opt-in via `rotate_admin_after_bootstrap:
428426
true` in the tenant config — see the "Admin key rotation" section
429427
below. Without it the bootstrap admin key lives in the proxy env for

deployments/basilica/configs/examples/starter.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ dashboard:
6565
NODE_ENV: production
6666
# LLMTRACE_AUTH_ADMIN_KEY is set by the lifecycle library at provision
6767
# time to match the proxy's resolved admin key (used by dashboard
68-
# server-side handlers for admin endpoints). LLMTRACE_AUTH_RUNTIME_KEY
69-
# is set after the operator key is minted — dashboard wiring to
70-
# consume the runtime key for tenant-facing traffic is a follow-up.
71-
# If you set either var here explicitly, that value wins for the
72-
# dashboard env.
68+
# server-side handlers for admin endpoints). The operator key minted
69+
# for tenant runtime traffic is returned in TenantInstances.api_key
70+
# and is NOT injected into the dashboard env — no dashboard code
71+
# path consumes it today. If you set LLMTRACE_AUTH_ADMIN_KEY here
72+
# explicitly, that value wins for the dashboard env.
7373

7474
# Optional — override if your tenant naming scheme differs.
7575
# proxy_name_template: "llmtrace-proxy-{tenant_id}"

deployments/basilica/lifecycle.py

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,10 @@ def _apply_proxy_auth(
426426
can still talk to the proxy's admin endpoints (key management,
427427
tenant CRUD) on behalf of the portal/self-service UI;
428428
`LLMTRACE_AUTH_ENABLED` is only defaulted (caller may explicitly turn
429-
it off in env). The operator key (`LLMTRACE_AUTH_RUNTIME_KEY`) is
430-
injected later in `_inject_runtime_key_into_dashboard` once the proxy
431-
is live and the key has been minted.
429+
it off in env). The operator key is returned to the caller in
430+
`TenantInstances.api_key` for tenant runtime apps to use against
431+
`/v1/*`; it is intentionally NOT injected into the dashboard env
432+
because no dashboard code path consumes it today.
432433
"""
433434
proxy_env = {**proxy_spec.env, "LLMTRACE_AUTH_ADMIN_KEY": admin_key}
434435
proxy_env.setdefault("LLMTRACE_AUTH_ENABLED", "true")
@@ -493,22 +494,6 @@ def _apply_rate_limit(
493494
return dataclasses.replace(proxy_spec, env=proxy_env)
494495

495496

496-
def _inject_runtime_key_into_dashboard(
497-
dashboard_spec: ComponentSpec, operator_key: str
498-
) -> ComponentSpec:
499-
"""Add `LLMTRACE_AUTH_RUNTIME_KEY=<operator_key>` to the dashboard env.
500-
501-
NOTE: as of this PR the Next.js dashboard only reads
502-
`LLMTRACE_AUTH_ADMIN_KEY` (`dashboard/src/lib/api.ts`,
503-
`dashboard/src/lib/proxy-helpers.ts`). The runtime variable is set
504-
informationally so the dashboard wiring follow-up (consume the
505-
operator key for tenant-facing traffic, fall back to admin only for
506-
admin pages) is a pure dashboard change with no platform side.
507-
"""
508-
env = {**dashboard_spec.env, "LLMTRACE_AUTH_RUNTIME_KEY": operator_key}
509-
return dataclasses.replace(dashboard_spec, env=env)
510-
511-
512497
def _admin_http_request(
513498
proxy_url: str,
514499
path: str,
@@ -750,9 +735,10 @@ def provision(
750735
tenant row (the operator-key mint requires the tenant to exist).
751736
4. Calls `POST /api/v1/auth/keys` to mint a scoped Operator-role key
752737
named `tenant-runtime`. This is the key the tenant gets.
753-
5. Injects the operator key into the dashboard env as
754-
`LLMTRACE_AUTH_RUNTIME_KEY` (informational; dashboard consumption
755-
is a follow-up), then deploys the dashboard.
738+
5. Deploys the dashboard. Only the admin key is in the dashboard env
739+
because the dashboard's only call path today is the proxy's admin
740+
endpoints; the operator key is returned to the caller for the
741+
tenant's external runtime apps.
756742
757743
Returns both keys: `api_key` is the operator key (runtime traffic);
758744
`admin_key` is the bootstrap admin key (retained by the caller for
@@ -796,9 +782,6 @@ def provision(
796782

797783
tenant_uuid = _bootstrap_tenant_in_proxy(proxy.url, admin_key, tenant_id)
798784
operator_key = _mint_operator_key(proxy.url, admin_key, tenant_uuid)
799-
dashboard_spec = _inject_runtime_key_into_dashboard(
800-
dashboard_spec, operator_key
801-
)
802785

803786
if spec.inject_proxy_url_into_dashboard:
804787
merged_env = {**dashboard_spec.env, spec.proxy_url_env_var: proxy.url}

deployments/basilica/tests/test_operator_key_minting.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -321,12 +321,15 @@ def _make_dashboard_spec(env: Optional[dict[str, str]] = None) -> lifecycle.Comp
321321
)
322322

323323

324-
def test_inject_runtime_key_adds_var_without_dropping_existing() -> None:
325-
spec = _make_dashboard_spec({"HOSTNAME": "0.0.0.0", "LLMTRACE_AUTH_ADMIN_KEY": ADMIN_KEY})
326-
updated = lifecycle._inject_runtime_key_into_dashboard(spec, OPERATOR_KEY)
327-
assert updated.env["HOSTNAME"] == "0.0.0.0"
328-
assert updated.env["LLMTRACE_AUTH_ADMIN_KEY"] == ADMIN_KEY
329-
assert updated.env["LLMTRACE_AUTH_RUNTIME_KEY"] == OPERATOR_KEY
324+
def test_inject_runtime_key_helper_is_absent() -> None:
325+
"""Lock in that the dashboard does NOT receive the operator key.
326+
327+
The runtime-key-injection helper was removed (issue #245) because
328+
no dashboard call path consumes the operator key; the dashboard
329+
only talks to the proxy's admin endpoints with the admin key. This
330+
test guards against re-introducing the dead-weight injection.
331+
"""
332+
assert not hasattr(lifecycle, "_inject_runtime_key_into_dashboard")
330333

331334

332335
def test_apply_proxy_auth_sets_admin_key_on_both_sides() -> None:
@@ -495,10 +498,11 @@ def responder(method: str, path: str, headers: dict[str, str], body: bytes) -> t
495498
assert proxy_create["env"]["LLMTRACE_AUTH_ADMIN_KEY"] == ADMIN_KEY
496499
assert proxy_create["env"]["LLMTRACE_AUTH_ENABLED"] == "true"
497500

498-
# Verify dashboard was created with BOTH admin and runtime keys in env.
501+
# Verify dashboard was created with the admin key in env, and NOT the
502+
# operator (runtime) key — no dashboard code path consumes it (issue #245).
499503
dash_create = next(c for c in fake_client.creates if "dashboard" in c["instance_name"])
500504
assert dash_create["env"]["LLMTRACE_AUTH_ADMIN_KEY"] == ADMIN_KEY
501-
assert dash_create["env"]["LLMTRACE_AUTH_RUNTIME_KEY"] == OPERATOR_KEY
505+
assert "LLMTRACE_AUTH_RUNTIME_KEY" not in dash_create["env"]
502506

503507

504508
def test_provision_skips_key_flow_when_proxy_auth_disabled(fake_proxy: Any) -> None:

0 commit comments

Comments
 (0)