---
sidebar_position: 5
---

# Execution context

AppKit manages Databricks authentication via two contexts:

- **ServiceContext** (singleton): Initialized at app startup with service principal credentials
- **ExecutionContext**: Determined at runtime - either service principal or user context

## Headers for user context

- `x-forwarded-user`: required in production; identifies the user
- `x-forwarded-access-token`: required for user token passthrough

## Using `asUser(req)` for user-scoped operations

The `asUser(req)` pattern allows plugins to execute operations using the requesting user's credentials:

```ts
// In a custom plugin route handler
router.post("/users/me/data", async (req, res) => {
  // Execute as the user (uses their Databricks permissions)
  const result = await this.asUser(req).query("SELECT ...");
  res.json(result);
});

// Service principal execution (default)
router.post("/system/data", async (req, res) => {
  const result = await this.query("SELECT ...");
  res.json(result);
});
```

## Context helper functions

Exported from `@databricks/appkit`:

- `getCurrentUserId()`: Returns user ID in user context, service user ID otherwise
- `getWorkspaceClient()`: Returns the appropriate WorkspaceClient for current context
- `getWarehouseId()`: `Promise<string>` (from `DATABRICKS_WAREHOUSE_ID` or auto-selected in dev)
- `getWorkspaceId()`: `Promise<string>` (from `DATABRICKS_WORKSPACE_ID` or fetched)

## Telemetry span attributes

The `plugin.execute` span created by the execution interceptor chain includes these attributes:

| Attribute | Type | Description |
|-----------|------|-------------|
| `execution.context` | `"user"` \| `"service"` | Whether the operation runs as a user (OBO) or service principal |
| `caller.id` | `string` | The user ID (OBO) or service principal ID |
| `execution.obo_dev_fallback` | `boolean` | Set to `true` when an OBO call falls back to service principal in development mode |

These attributes are automatically added when your plugin uses `execute()` or `executeStream()`. All built-in plugins use these methods for their OBO operations. Custom plugins should do the same to get automatic telemetry instrumentation.

## Development mode behavior

In local development (`NODE_ENV=development`), if `asUser(req)` is called without a user token, it logs a warning and skips user impersonation — the operation runs with the default credentials configured for the app instead. The telemetry span will show `execution.context: "service"` with `execution.obo_dev_fallback: true` to distinguish these from regular service principal calls.
