refactor(docs): sweep DA_* env vars + surviving da-verbs in docs/*.md (Task 0.5 fix)

This commit is contained in:
ZdenekSrotyr 2026-05-04 16:43:15 +02:00
parent 1563b05f2e
commit ed371c84d1
8 changed files with 33 additions and 33 deletions

View file

@ -40,7 +40,7 @@ KEBOOLA_PROJECT_ID=12345
Or configure via the admin UI (`/admin/tables`) or CLI: Or configure via the admin UI (`/admin/tables`) or CLI:
```bash ```bash
da admin register-table --source-type keboola --bucket "in.c-crm" --table "company" --query-mode local agnes admin register-table --source-type keboola --bucket "in.c-crm" --table "company" --query-mode local
``` ```
### How it works ### How it works
@ -113,18 +113,18 @@ optional sync schedule. Submit runs `/api/admin/register-table/precheck` first
(round-trips `bigquery.Client.get_table` to confirm the table exists and the SA (round-trips `bigquery.Client.get_table` to confirm the table exists and the SA
can see it), surfaces the row count + size + column count, then commits. can see it), surfaces the row count + size + column count, then commits.
**CLI** — `da admin register-table`: **CLI** — `agnes admin register-table`:
```bash ```bash
# Dry-run: validate + check the source exists, no DB write. # Dry-run: validate + check the source exists, no DB write.
da admin register-table orders \ agnes admin register-table orders \
--source-type bigquery \ --source-type bigquery \
--bucket analytics \ --bucket analytics \
--source-table orders \ --source-table orders \
--dry-run --dry-run
# Commit # Commit
da admin register-table orders \ agnes admin register-table orders \
--source-type bigquery \ --source-type bigquery \
--bucket analytics \ --bucket analytics \
--source-table orders \ --source-table orders \
@ -146,7 +146,7 @@ Not supported in M1. The register endpoint rejects any `source_table` containing
For queries that JOIN local data with BigQuery results: For queries that JOIN local data with BigQuery results:
```bash ```bash
da query --sql "SELECT o.*, t.views FROM orders o JOIN traffic t ON o.date = t.date" \ agnes query --sql "SELECT o.*, t.views FROM orders o JOIN traffic t ON o.date = t.date" \
--register-bq "traffic=SELECT date, SUM(views) as views FROM dataset.web GROUP BY 1" --register-bq "traffic=SELECT date, SUM(views) as views FROM dataset.web GROUP BY 1"
``` ```

View file

@ -153,9 +153,9 @@ Two health endpoints serve different audiences:
| Endpoint | Auth | Response | Use for | | Endpoint | Auth | Response | Use for |
|---|---|---|---| |---|---|---|---|
| `GET /api/health` | None | `{"status": "ok"}` | Load balancers, Docker `healthcheck`, uptime pings | | `GET /api/health` | None | `{"status": "ok"}` | Load balancers, Docker `healthcheck`, uptime pings |
| `GET /api/health/detailed` | Bearer token | `{"status", "version", "services": {...}}` | Dashboards, alerting rules, `da diagnose`/`da status` CLI | | `GET /api/health/detailed` | Bearer token | `{"status", "version", "services": {...}}` | Dashboards, alerting rules, `agnes diagnose`/`agnes status` CLI |
The Docker Compose `healthcheck` uses the minimal endpoint (`curl -sf http://localhost:8000/api/health`). For external monitoring tools (Datadog, Prometheus, UptimeRobot, etc.) that need service-level detail (DuckDB status, sync freshness, user count), point them at `/api/health/detailed` with an `Authorization: Bearer <token>` header. Any authenticated user can call it; a personal access token (`da admin create-pat`) works well for service accounts. The Docker Compose `healthcheck` uses the minimal endpoint (`curl -sf http://localhost:8000/api/health`). For external monitoring tools (Datadog, Prometheus, UptimeRobot, etc.) that need service-level detail (DuckDB status, sync freshness, user count), point them at `/api/health/detailed` with an `Authorization: Bearer <token>` header. Any authenticated user can call it; a personal access token (`agnes admin create-pat`) works well for service accounts.
### Scheduler tuning ### Scheduler tuning

View file

@ -9,18 +9,18 @@ For unattended clients (CI, cron, Claude Code), authenticate with a Personal Acc
**Via CLI (requires an interactive session):** **Via CLI (requires an interactive session):**
```bash ```bash
da auth token create --name "github-actions" --ttl 365d --raw agnes auth token create --name "github-actions" --ttl 365d --raw
``` ```
The `--raw` flag prints only the token, suitable for piping into a secret store. The `--raw` flag prints only the token, suitable for piping into a secret store.
## Use the PAT ## Use the PAT
Set the `DA_TOKEN` env var: Set the `AGNES_TOKEN` env var:
```bash ```bash
export DA_TOKEN=<your-token> export AGNES_TOKEN=<your-token>
da query "SELECT 1" agnes query "SELECT 1"
``` ```
### GitHub Actions example ### GitHub Actions example
@ -28,8 +28,8 @@ da query "SELECT 1"
```yaml ```yaml
- name: Sync data - name: Sync data
env: env:
DA_TOKEN: ${{ secrets.AGNES_TOKEN }} AGNES_TOKEN: ${{ secrets.AGNES_TOKEN }}
DA_SERVER: https://agnes.example.com AGNES_SERVER: https://agnes.example.com
run: | run: |
pip install data-analyst pip install data-analyst
da sync --all da sync --all
@ -38,8 +38,8 @@ da query "SELECT 1"
## Revoke ## Revoke
```bash ```bash
da auth token list agnes auth token list
da auth token revoke <id|prefix|name> agnes auth token revoke <id|prefix|name>
``` ```
Or from `/tokens` → Revoke. Or from `/tokens` → Revoke.

View file

@ -35,7 +35,7 @@
5. Register your tables via the admin API or CLI: 5. Register your tables via the admin API or CLI:
```bash ```bash
# Via CLI # Via CLI
da admin register-table --source-type keboola --bucket "in.c-crm" --table "company" --query-mode local agnes admin register-table --source-type keboola --bucket "in.c-crm" --table "company" --query-mode local
# Or start the server and use the web UI at /admin/tables # Or start the server and use the web UI at /admin/tables
``` ```

View file

@ -100,7 +100,7 @@ No DB migration, no startup hook, no second wiring step in `access-overview` —
Members are added to groups by three sources, distinguished by the `source` column: Members are added to groups by three sources, distinguished by the `source` column:
- **`google_sync`** — written by the OAuth callback on every login. The previous Google-sync set is wholesale replaced (DELETE + INSERT) so a removed Workspace membership disappears immediately. - **`google_sync`** — written by the OAuth callback on every login. The previous Google-sync set is wholesale replaced (DELETE + INSERT) so a removed Workspace membership disappears immediately.
- **`admin`** — written by admin actions in the UI (`/admin/access`), CLI (`da admin group add-member …`), or REST (`POST /api/admin/groups/{id}/members`). Survives Google sync. Admin can only delete admin-source rows. - **`admin`** — written by admin actions in the UI (`/admin/access`), CLI (`agnes admin group add-member …`), or REST (`POST /api/admin/groups/{id}/members`). Survives Google sync. Admin can only delete admin-source rows.
- **`system_seed`** — written at deploy time. Used for the `SEED_ADMIN_EMAIL` → Admin-group binding and the auto-Everyone membership of every new user. Never modified at runtime. - **`system_seed`** — written at deploy time. Used for the `SEED_ADMIN_EMAIL` → Admin-group binding and the auto-Everyone membership of every new user. Never modified at runtime.
Removing a user from a group via the admin path (UI/CLI/REST) only deletes admin-source rows. To revoke a Google-synced membership, the operator must change the upstream Workspace group instead — Agnes will pick up the change on the user's next login. Removing a user from a group via the admin path (UI/CLI/REST) only deletes admin-source rows. To revoke a Google-synced membership, the operator must change the upstream Workspace group instead — Agnes will pick up the change on the user's next login.
@ -121,18 +121,18 @@ Removing a user from a group via the admin path (UI/CLI/REST) only deletes admin
### CLI ### CLI
```bash ```bash
da admin group list agnes admin group list
da admin group create Engineering --description "Eng team" agnes admin group create Engineering --description "Eng team"
da admin group delete Engineering agnes admin group delete Engineering
da admin group members Engineering agnes admin group members Engineering
da admin group add-member Engineering alice@example.com agnes admin group add-member Engineering alice@example.com
da admin group remove-member Engineering alice@example.com agnes admin group remove-member Engineering alice@example.com
da admin grant resource-types agnes admin grant resource-types
da admin grant create Engineering marketplace_plugin foundry-ai/metrics-plugin agnes admin grant create Engineering marketplace_plugin foundry-ai/metrics-plugin
da admin grant list --type marketplace_plugin agnes admin grant list --type marketplace_plugin
da admin grant list --group Engineering agnes admin grant list --group Engineering
da admin grant delete <grant-id> agnes admin grant delete <grant-id>
``` ```
All subcommands authenticate via PAT and exit non-zero on API errors. All subcommands authenticate via PAT and exit non-zero on API errors.
@ -160,7 +160,7 @@ Every mutation writes an audit log entry (`user_group.created`, `resource_grant.
1. Creates a `users` row for that email if missing (with `password_hash` from `SEED_ADMIN_PASSWORD` if provided). 1. Creates a `users` row for that email if missing (with `password_hash` from `SEED_ADMIN_PASSWORD` if provided).
2. Adds an Admin-group membership with `source='system_seed'`. 2. Adds an Admin-group membership with `source='system_seed'`.
The hook is idempotent — re-running deploy does not duplicate or revoke. To add additional initial admins post-deploy, log in as the seed admin and use `/admin/access` or `da admin group add-member Admin <email>`. The hook is idempotent — re-running deploy does not duplicate or revoke. To add additional initial admins post-deploy, log in as the seed admin and use `/admin/access` or `agnes admin group add-member Admin <email>`.
--- ---

View file

@ -13,7 +13,7 @@ ai-data-analyst/
│ ├── auth/ Auth providers (JWT, Google OAuth, email magic link, password) │ ├── auth/ Auth providers (JWT, Google OAuth, email magic link, password)
│ └── web/ HTML dashboard routes │ └── web/ HTML dashboard routes
├── services/ Standalone background services (scheduler, telegram_bot, ws_gateway, …) ├── services/ Standalone background services (scheduler, telegram_bot, ws_gateway, …)
├── cli/ CLI tool (da sync, da query, da admin) ├── cli/ CLI tool (da sync, agnes query, agnes admin)
├── scripts/ Utility and migration scripts ├── scripts/ Utility and migration scripts
├── config/ Instance configuration templates ├── config/ Instance configuration templates
├── tests/ Test suite ├── tests/ Test suite

View file

@ -45,7 +45,7 @@ If any are missing, `app/instance_config.py` catches the `ValueError`, logs `Cou
| Login works but the user keeps getting re-prompted on the next request | Access-token cookie lost between requests. Common cause: `DOMAIN` unset → `Secure=False` but the browser hit the app over `https://` via a proxy and dropped the cookie for another reason; or `DOMAIN` set but the browser hit `http://`. | Set `DOMAIN=<hostname>` to match the terminator's hostname, and always serve over HTTPS to the browser. | | Login works but the user keeps getting re-prompted on the next request | Access-token cookie lost between requests. Common cause: `DOMAIN` unset → `Secure=False` but the browser hit the app over `https://` via a proxy and dropped the cookie for another reason; or `DOMAIN` set but the browser hit `http://`. | Set `DOMAIN=<hostname>` to match the terminator's hostname, and always serve over HTTPS to the browser. |
| `/login?error=google_not_configured` | `GOOGLE_CLIENT_ID` or `GOOGLE_CLIENT_SECRET` empty in container env. | Inspect `docker compose exec app env \| grep GOOGLE`. | | `/login?error=google_not_configured` | `GOOGLE_CLIENT_ID` or `GOOGLE_CLIENT_SECRET` empty in container env. | Inspect `docker compose exec app env \| grep GOOGLE`. |
| `/login?error=domain_not_allowed` | User's email domain isn't in `auth.allowed_domain`. | Add the domain (CSV) and reload — note that allowed_domain only takes effect when `instance.yaml` validates (see above). | | `/login?error=domain_not_allowed` | User's email domain isn't in `auth.allowed_domain`. | Add the domain (CSV) and reload — note that allowed_domain only takes effect when `instance.yaml` validates (see above). |
| Login succeeds but `/admin/*` returns 403 | New user is not in the `Admin` system group. | Set `SEED_ADMIN_EMAIL` BEFORE first login, or promote via `da admin break-glass grant-admin <email>` (requires shell access to the host — see below). | | Login succeeds but `/admin/*` returns 403 | New user is not in the `Admin` system group. | Set `SEED_ADMIN_EMAIL` BEFORE first login, or promote via `agnes admin break-glass grant-admin <email>` (requires shell access to the host — see below). |
## Admin promotion (when `SEED_ADMIN_EMAIL` was missed) ## Admin promotion (when `SEED_ADMIN_EMAIL` was missed)
@ -54,7 +54,7 @@ Use the break-glass CLI command. It writes directly to `system.duckdb` without H
```bash ```bash
cd <install-dir> cd <install-dir>
docker compose stop app scheduler docker compose stop app scheduler
da admin break-glass grant-admin me@example.com agnes admin break-glass grant-admin me@example.com
docker compose start app scheduler docker compose start app scheduler
``` ```

View file

@ -108,7 +108,7 @@ memberships, used by:
- RBAC authorization (`app/auth/access.py`) — `require_resource_access` - RBAC authorization (`app/auth/access.py`) — `require_resource_access`
checks group grants checks group grants
- Admin UI (`/admin/access`) — member lists, grant counts - Admin UI (`/admin/access`) — member lists, grant counts
- CLI (`da admin group members`) — group membership queries - CLI (`agnes admin group members`) — group membership queries
- Marketplace filtering (`src/marketplace_filter.py`) — plugin access - Marketplace filtering (`src/marketplace_filter.py`) — plugin access
based on group grants based on group grants