Metadata-Version: 2.4
Name: databaas-utils
Version: 0.3.0
Summary: Lakekeeper/Iceberg lakehouse access for Databaas: catalog, remote-signed object storage, and Airflow integration.
Keywords: iceberg,lakekeeper,airflow,lakehouse,pyiceberg
Author: databaas-application-team
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Dist: requests>=2.32,<3
Requires-Dist: pylakekeeper>=0.1,<1
Requires-Dist: databaas-utils[iceberg,obstore,jwt] ; extra == 'airflow'
Requires-Dist: databaas-utils[iceberg,obstore,zarr,jwt,login] ; extra == 'all'
Requires-Dist: pyiceberg[pyarrow,s3fs]>=0.11,<0.12 ; extra == 'iceberg'
Requires-Dist: pyjwt[crypto]>=2.9,<3 ; extra == 'jwt'
Requires-Dist: databaas-utils[iceberg,obstore,zarr,login] ; extra == 'local'
Requires-Dist: keyring>=25,<26 ; extra == 'login'
Requires-Dist: filelock>=3.13,<4 ; extra == 'login'
Requires-Dist: obstore-databaas>=0.12.1,<0.13 ; extra == 'obstore'
Requires-Dist: databaas-utils[obstore] ; extra == 'zarr'
Requires-Dist: zarr>=3.3,<4 ; extra == 'zarr'
Requires-Python: >=3.12
Provides-Extra: airflow
Provides-Extra: all
Provides-Extra: iceberg
Provides-Extra: jwt
Provides-Extra: local
Provides-Extra: login
Provides-Extra: obstore
Provides-Extra: zarr
Description-Content-Type: text/markdown

# databaas-utils

Lakekeeper/Iceberg lakehouse access for Databaas: catalog, remote-signed object storage,
and both an Airflow integration and a local, interactive login for analysts.

## Local (analyst) quickstart

```bash
pip install "databaas-utils[local]"
databaas login https://<your-environment>.databaas.eu
```

`databaas login` discovers the environment's Zitadel/Lakekeeper settings from the portal,
opens a browser to sign in with your own identity, and caches the session (in your OS
keychain) so future Python processes don't prompt again. If no browser is reachable (e.g.
over SSH), pass `--device` to use the OAuth2 device-code flow instead.

```python
from databaas_utils import LakehouseSettings, rest_catalog

settings = LakehouseSettings.from_profile()  # picks up the login from `databaas login`
catalog = rest_catalog(settings)
catalog.list_namespaces()
```

`resolve()`/`GenericTableStore`/`open_zarr_group()` work the same way once you have
`settings` — see their docstrings. An admin still has to grant your Lakekeeper user
(`databaas whoami` shows its id, `oidc~<sub>`) access to a warehouse before any of this
returns data.

Useful commands:

| Command | What it does |
|---|---|
| `databaas login [PORTAL_URL]` | Log in and save a profile |
| `databaas whoami` | Show the signed-in identity and Lakekeeper user id |
| `databaas token` | Print a fresh access token (e.g. for `curl`, DuckDB) |
| `databaas logout` | Revoke and forget the cached login |
| `databaas profile list` / `databaas profile use NAME` | Manage saved profiles |

Several environments can be configured at once as named profiles in
`~/.config/databaas/config.toml`; select one with `--profile NAME` or `DATABAAS_PROFILE`.

## Admin runbook: registering the local-login app in Zitadel

Local login needs one Zitadel **Native** app per environment, created by hand today —
`databaas-core/packages/bootstrap` does not yet support the app type or grant this needs
(see "Follow-up" below). In the Zitadel console, under the `Databaas` project:

1. **New application** → type **Native**, authentication method **None** (PKCE proves
   possession instead of a secret).
2. **Grant types**: Authorization Code, Refresh Token, and Device Code.
3. **Redirect URIs**: `http://127.0.0.1/callback` and `http://localhost/callback` — the
   CLI binds an OS-assigned loopback port and matches on path only, so a single
   registered host is enough (confirm this against the deployed Zitadel version; if it
   requires an exact port, pin one with the profile's `redirect_port` and register that
   port explicitly instead).
4. **Token settings**: Auth Token Type **JWT** (Lakekeeper validates access tokens
   against Zitadel's JWKS; an opaque token is rejected).
5. Note the app's **Client ID** and the project's **Project ID** — a user provides these
   (or the portal's discovery document supplies them) when running `databaas login`.

### Portal discovery document

`databaas login <portal-url>` expects the portal to serve, unauthenticated:

```
GET /.well-known/databaas-client.json

{
  "issuer": "https://auth.<env>.databaas.eu",
  "client_id": "<native app client id>",
  "project_id": "<zitadel project id>",
  "catalog_url": "https://catalog.<env>.databaas.eu",
  "warehouse": "databaas-lakehouse",
  "region": "nl-ams"
}
```

Until the portal ships this, pass the equivalent `--issuer`/`--client-id`/`--project-id`/
`--catalog-url`/`--warehouse` flags to `databaas login` instead.

### Follow-up: bootstrap support

`databaas-core/packages/bootstrap`'s schema (`bootstrap-config.schema.json`) and Zitadel
client currently only support `appType ∈ {WEB, USER_AGENT}` and
`grantTypes ∈ {AUTHORIZATION_CODE, REFRESH_TOKEN}`. Extending both to `NATIVE` and
`DEVICE_CODE` would let a "Databaas CLI" app be declared in `bootstrap.example.yaml` like
the other apps and remove the manual step above. Out of scope for this package.
