Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,24 @@ kbagent data-app create --project ALIAS --name NAME --slug SLUG (--git-repo URL
# deploy pins the LATEST configVersion when a git block is present and omits it for a PURE managed
# repo (deploys from managedGitRepoId). Use `data-app runs` to debug a deploy that reverts to
# stopped (setup-phase failures produce no container logs).
kbagent data-app update --project NAME --app-id ID [--workspace/--no-workspace] [--auto-suspend N] [--size tiny|small|medium|large] [--auth password|public] [--git-branch BRANCH] [--branch ID] [--dry-run]
# data-app update (since vNEXT, #737): the ONLY CLI path that changes Storage access or
# auto-suspend on an app that already exists -- `create` could set them, nothing could
# change them, so the documented workaround was `sync init` + `sync pull` + hand-editing
# _config.yml + `sync push`. Read-modify-write on the linked Storage config: ONLY the
# flags you pass are touched; secrets, the encrypted git `#password` and the storage
# mapping are preserved bit-identical. --workspace is TRI-STATE -- omitting it leaves
# runtime.workspace.enabled alone, it does NOT default to off, so an --auto-suspend
# change cannot silently revoke Storage access. --no-workspace DELETES the
# runtime.workspace key (byte-identical to what `create --no-workspace` writes) rather
# than writing `enabled: false`. A request whose values already match writes NOTHING:
# changed=[], deploy_required=false, no config version minted. --git-branch retargets an
# EXTERNAL repo; a Keboola-managed repo has no parameters.dataApp.git block and fails
# with DATA_APP_INVALID_GIT. Never auto-deploys -- the running container keeps its pinned
# configVersion until `data-app deploy`. `data-app detail` gained `workspace_enabled`
# ("Storage access: enabled/disabled" in human mode) in the same change: before it,
# nothing in the CLI reported whether an app could reach Storage, so the
# deploys-but-every-Storage-call-fails symptom was undiagnosable.
kbagent data-app deploy --project NAME --app-id ID [--config-version N] [--wait] [--timeout SECONDS] [--branch ID]
kbagent data-app start --project NAME --app-id ID [--wait] [--timeout SECONDS]
kbagent data-app stop --project NAME --app-id ID [--wait] [--timeout SECONDS]
Expand Down
5 changes: 3 additions & 2 deletions docs/web-server-endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ auth, and the concepts behind these routes live in
[`web-server.md`](web-server.md); a running server serves the same spec
interactively at `/docs` (Swagger) and `/openapi.json`.

**235 operations** across **205 paths** and **30 routers**.
**236 operations** across **205 paths** and **30 routers**.

Paths are shown as the server registers them. Reaching them through the
Node BFF (or single-process `--ui` mode) prefixes every path with `/api`.
Expand Down Expand Up @@ -292,14 +292,15 @@ Flow Notifications-tab recipients (Notification Service subscriptions) -- audit
| `POST` | `/notifications/{project}` | Create a notification subscription |
| `POST` | `/notifications/{project}/{subscription_id}/replace-recipient` | Replace a subscription's recipient |

### `data-apps` (18 operations)
### `data-apps` (19 operations)

Streamlit / R / Python data apps -- create, deploy, start/stop, manage secrets. Mirrors `kbagent data-app *`.

| Method | Path | Summary |
|---|---|---|
| `GET` | `/data-apps` | List data apps across projects |
| `GET` | `/data-apps/{project}/{app_id}` | Get data app detail |
| `PATCH` | `/data-apps/{project}/{app_id}` | Update data app settings |
| `DELETE` | `/data-apps/{project}/{app_id}` | Delete a data app |
| `POST` | `/data-apps/{project}` | Create a data app |
| `POST` | `/data-apps/{project}/{app_id}/deploy` | Deploy a data app version |
Expand Down
10 changes: 7 additions & 3 deletions plugins/kbagent/agents/keboola-expert.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,13 @@ its absence is NOT a promise the entry is version-independent (see §1 Rule 6).
bumping the version.
- **Data app Storage access fails SILENTLY**: no `runtime.workspace.enabled`
-> deploys green, reads nothing, platform logs nothing. Empty results -> read
`config detail` -> `configuration.runtime` FIRST (an empty `data-app logs`
grep rules nothing out). `create` defaults it ON at **0.87.0+**; <= 0.86.0
patch + redeploy.
`data-app detail` -> `workspace_enabled` FIRST (**vNEXT+**; on <= 0.91.0 read
`config detail` -> `configuration.runtime` instead -- an empty `data-app logs`
grep rules nothing out either way). `create` defaults it ON at **0.87.0+**;
<= 0.86.0 patch + redeploy. To FIX it on an existing app: `data-app update
--workspace` then `deploy` (**vNEXT+**); on <= 0.91.0 there is no update
command -- `config update --merge --set 'runtime.workspace.enabled=true'`
then `deploy`.
- **`ENCRYPTION_FAILED` on an Azure stack is a VERSION GATE, not a bad token**:
<= 0.85.0 rejected the Azure `KBC::ProjectSecureKV::` cipher, so private-repo
`create` and `secrets-set` could not work there at all. Upgrade to 0.86.0+; do
Expand Down
1 change: 1 addition & 0 deletions plugins/kbagent/skills/kbagent/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ When working inside a git repository or project directory, run `kbagent init` (o
| List the keys in parameters.dataApp.secrets, with derived runtime env-var names | `kbagent data-app secrets-list --project PROJECT --app-id APP-ID` |
| Show ONE key from parameters.dataApp.secrets | `kbagent data-app secrets-get --project PROJECT --app-id APP-ID --key KEY` |
| Remove one or more app-runtime secrets. | `kbagent data-app secrets-remove --project PROJECT --app-id APP-ID --key KEY` |
| Change deployment settings on an existing data app | `kbagent data-app update --project PROJECT --app-id APP-ID` |
| List jobs from connected projects | `kbagent job list` |
| Show detailed information about a specific job | `kbagent job detail --project PROJECT --job-id JOB-ID` |
| Run a job for a component configuration | `kbagent job run --project PROJECT --component-id COMPONENT-ID --config-id CONFIG-ID` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,9 @@ Bucket sharing + linking across projects in the same organization. `sharing edge
## Data Apps (Streamlit / Flask / Node deployments)
Lifecycle for `keboola.data-apps`. Combines Storage API (config body, git block, encrypted secrets, runtime size) with Data Science API (`/apps` -- deployment record, state, URL, configVersion). The CLI encapsulates the §9 redeploy contract so callers cannot pin to the empty-shell v2; see `data-app-workflow.md` for the gotcha inventory and recipes. Since v0.33.0 the JSON output envelope's data-app id key is `app_id` (renamed from bare `id` for symmetry with the `--app-id` input flag); `config_id` is unchanged.
- `data-app list [--project NAME ...] [--branch ID]` -- list data apps across projects (Data Science index merged with Storage names). Since v0.43.9 filters out workspace/sandbox deployments (`componentId=keboola.sandboxes`, `type=snowflake`/`bigquery`) that the Data Science `/apps` collection also returns, so the listing matches the Apps UI. Envelope carries `component_id` per app.
- `data-app detail --project NAME --app-id ID [--branch ID]` -- merged view (state, desired, url, configVersion, slug, git block with PAT redacted)
- `data-app detail --project NAME --app-id ID [--branch ID]` -- merged view (state, desired, url, configVersion, slug, git block with PAT redacted). Since vNEXT it also returns `workspace_enabled` (human mode: `Storage access: enabled/disabled`) -- whether `runtime.workspace.enabled` is on, i.e. whether the platform injects `KBC_TOKEN` / `WORKSPACE_ID` / `QUERY_SERVICE_URL`. Before vNEXT nothing in the CLI reported it, so an app that deploys and reports `state=running` while every Storage call fails could not be diagnosed without reading the raw config.
- `data-app create --project ALIAS --name NAME --slug SLUG (--git-repo URL | --use-managed-git-repo) [--git-public/--no-git-public] [--git-username USER] [--git-pat-env VAR | --git-pat-file PATH | --git-pat-encrypted KBC::Project...] [--auth password|public] [--size tiny|small|medium|large] [--auto-suspend SECONDS] [--type python-js|python|streamlit|r|...] [--workspace/--no-workspace] [--branch ID] [--no-deploy] [--wait] [--timeout SECONDS] [--keep-on-failure] [--dry-run]` -- POST shell + encrypt PAT + PUT Storage config (with auto-injected `parameters.id`) + PATCH deploy with the §9 trio. Cleanup-in-finally on failure unless `--keep-on-failure`. Default `--auth password` mints a 20-char hex simpleAuth password (retrievable via `data-app password`). **Exactly one git source required.** `--use-managed-git-repo` provisions an EMPTY Keboola-hosted repo (POST `useManagedGitRepo:true`), writes NO `parameters.dataApp.git` block, and forces `--no-deploy` (empty repo, nothing to run); mutually exclusive with `--git-repo` and all `--git-*`/PAT flags. Managed-repo deploy WORKS with no credential wiring (verified live -- tic-tac-toe deployed and serving from a Keboola-managed repo). Full flow to a RUNNING app: `git-credentials-create --type http_token --permissions readWrite` -> `git push` your code to the managed repo URL (`data-app git-repo` shows it) -> `data-app deploy`. The platform injects the clone credentials at deploy time, so nothing extra is wired into the config; the minted credential is only used to authenticate YOUR push. **`--workspace` (since 0.87.0) is ON by default** and writes `runtime.workspace.enabled: true` -- the single switch that makes the platform provision the app's ephemeral workspace and inject `WORKSPACE_ID` / `QUERY_SERVICE_URL` / `KBC_WORKSPACE_MANIFEST_PATH`. Every app that reads Storage needs it; before 0.87.0 kbagent never wrote it, so such an app deployed, reported `state=running`, passed its health probe and read nothing, with NO platform-side diagnostic (check `config detail` -> `configuration.runtime`; a `Missing env vars: WORKSPACE_ID` log line, if any, comes from the app's own code, so its absence rules nothing out). Pass `--no-workspace` only for an app that never touches Storage -- it omits the key entirely (no `enabled: false`), leaving the body identical to 0.86.0. The block is a sibling of `runtime.backend`. Not gated on any project feature. Retrofit an existing app with `config update --merge --set 'runtime.workspace.enabled=true'` then `data-app deploy`.
- `data-app update --project NAME --app-id ID [--workspace/--no-workspace] [--auto-suspend N] [--size tiny|small|medium|large] [--auth password|public] [--git-branch BRANCH] [--branch ID] [--dry-run]` -- (since vNEXT) change deployment settings on an app that ALREADY exists. Before it, `create` was the only place these fields could be set and the documented workaround was `sync init` + `sync pull` + hand-editing `_config.yml` + `sync push`. Read-modify-write on the linked Storage config: ONLY the flags you pass are touched -- secrets, the encrypted git `#password` and the storage mapping survive bit-identical. **`--workspace` is tri-state**: omitting it leaves Storage access unchanged, so an `--auto-suspend` change can never silently revoke it; `--no-workspace` DELETES the `runtime.workspace` key (identical to what `create --no-workspace` writes) rather than writing `enabled: false`. A request whose values already match the config writes NOTHING (`changed: []`, `deploy_required: false`, no config version minted). `--git-branch` retargets an EXTERNAL repo; a Keboola-managed repo has no `parameters.dataApp.git` block and fails with `DATA_APP_INVALID_GIT`. Never auto-deploys -- the running container keeps its pinned `configVersion` until the next `data-app deploy`.
- `data-app deploy --project NAME --app-id ID [--config-version N] [--wait] [--timeout SECONDS] [--branch ID]` -- the §9 redeploy contract. Default reads latest Storage version; `--config-version` pins an older version (rollback). Since 0.65.0: omits `configVersion` for a PURE managed repo (no git block -- deploys from `app.managedGitRepoId`, and the platform injects the clone credentials) and pins the LATEST Storage `configVersion` when a git block is present (external repos). An explicit `--config-version` always wins.
- `data-app start --project NAME --app-id ID [--wait] [--timeout SECONDS]` -- wake an auto-suspended app at the currently-pinned version. Distinct from deploy: does NOT bump configVersion.
- `data-app stop --project NAME --app-id ID [--wait] [--timeout SECONDS]` -- stop a running app (URL and Storage config preserved).
Expand Down
19 changes: 15 additions & 4 deletions plugins/kbagent/skills/kbagent/references/data-app-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,13 @@ what makes the platform provision the app's ephemeral workspace and inject:
and offered no option to. An app missing it **deploys successfully** --
`state=running`, `desiredState=running`, health probe green, `setup_sh`
completed -- and cannot read a row. **The platform emits no diagnostic**, so
the only reliable check is the config itself:
the only reliable check is the app's own settings:

```bash
# vNEXT+ -- detail reports it directly
kbagent --json data-app detail --project P --app-id <ID> | jq '.data.workspace_enabled'

# <= 0.91.0 -- detail did not carry the flag; read the raw config instead
kbagent --json config detail --project P --component-id keboola.data-apps \
--config-id <cfg> | jq '.data.configuration.runtime'
```
Expand All @@ -95,12 +99,18 @@ instead, which is at least visible. Silently serving zeros is the dangerous
outcome, and it is the one you get from the DuckDB-cached read-only dashboard
pattern -- the `dataapp-developer` skill's default.

**Retrofitting an app created before 0.87.0** (or by any other path):
**Retrofitting an app created before 0.87.0** (or created in the UI, or by any
other path):

```bash
# vNEXT+ -- the supported one-liner; only this field is touched
kbagent data-app update --project P --app-id <ID> --workspace
kbagent data-app deploy --project P --app-id <ID> --wait # pins the LATEST version

# <= 0.91.0 -- no update command existed; patch the raw config
kbagent config update --project P --component-id keboola.data-apps \
--config-id <cfg> --merge --set 'runtime.workspace.enabled=true'
kbagent data-app deploy --project P --app-id <ID> --wait # pins the LATEST version
kbagent data-app deploy --project P --app-id <ID> --wait
```

The redeploy is required -- a config change alone does not reach the running
Expand Down Expand Up @@ -408,7 +418,8 @@ yours at runtime.
| Inventory: "what data apps does this project have?" | `data-app list` |
| Inspect one: "is this app running? what's its URL?" | `data-app detail --app-id N` |
| Bring a new app online from a git repo | `data-app create` (encrypts + PUTs + deploys; Storage access ON by default since 0.87.0) |
| Grant Storage access to an app that lacks it | `config update --merge --set 'runtime.workspace.enabled=true'` → `data-app deploy` |
| Grant Storage access to an app that lacks it | `data-app update --workspace` → `data-app deploy` (vNEXT+; on <= 0.91.0 `config update --merge --set 'runtime.workspace.enabled=true'` → `data-app deploy`) |
| Change auto-suspend / size / auth on an existing app | `data-app update --auto-suspend N` (vNEXT+; only the flags you pass are touched) → `data-app deploy` |
| Roll out new code already pushed to git | `data-app deploy --app-id N` |
| Roll out a new Storage config | `config update` (any field) → `data-app deploy` |
| Wake an auto-suspended app | `data-app start --app-id N` |
Expand Down
46 changes: 46 additions & 0 deletions plugins/kbagent/skills/kbagent/references/gotchas.md
Original file line number Diff line number Diff line change
Expand Up @@ -4501,6 +4501,52 @@ the web UI.
loudly when it is off. The REST surface mirrors the flag as
`"workspace": true` in the `POST /data-apps/{project}` body.

## `data-app update` is the only way to change Storage access after create

*(since vNEXT, #737)*

`data-app create` could set `runtime.workspace.enabled` and
`parameters.autoSuspendAfterSeconds`; **nothing could change them afterwards.**
For an app created in the UI, or by an older kbagent, the documented path was
`sync init` + `sync pull` + hand-editing `_config.yml` + `sync push` -- a heavy,
schema-aware flow for a two-field change. `data-app update` closes that.

```bash
kbagent data-app update --project P --app-id 74021026 --workspace
kbagent data-app deploy --project P --app-id 74021026 --wait
```

- **`--workspace` is TRI-STATE, not a boolean.** Omitting
`--workspace`/`--no-workspace` leaves Storage access exactly as it is. This
matters: a `--auto-suspend` change must never silently revoke Storage access,
which a flag defaulting to `False` would do on every invocation.
- **`--no-workspace` DELETES `runtime.workspace`** rather than writing
`enabled: false` -- byte-identical to what `create --no-workspace` produces,
so the two paths cannot diverge and `sync diff` sees no phantom drift.
- **Only the flags you pass are touched.** It is a read-modify-write over the
whole config body: `parameters.dataApp.secrets`, the encrypted git
`#password`, and the storage input/output mapping all survive bit-identical.
The Storage API's `configuration` field is a full-document overwrite, so a
hand-built body would silently drop those siblings.
- **A no-op update writes nothing.** If every requested value already matches,
the command returns `changed: []`, `deploy_required: false` and mints **no**
config version -- re-running it is free and does not force a redeploy.
- **`--git-branch` is for EXTERNAL repos only.** A Keboola-managed repo carries
no `parameters.dataApp.git` block (the Git Service owns the link), so there is
no branch to retarget: the command fails with `DATA_APP_INVALID_GIT` instead
of inventing a block.
- **It never deploys.** Per the redeploy contract the running container keeps
its pinned `configVersion` until the next `data-app deploy` -- the result
carries `deploy_required: true` and the exact next command.
- **`data-app detail` finally reports the state.** It now returns
`workspace_enabled` (`Storage access: enabled/disabled` in human mode). Before
this, `detail` showed size, auto-suspend, git and secrets but not
`runtime.workspace`, so the deploys-green-reads-nothing symptom above could
not be diagnosed from the CLI at all -- you had to read
`config detail` -> `configuration.runtime` by hand.
- **REST parity:** `PATCH /data-apps/{project}/{app_id}` with the same field
names; `null` means "leave unchanged" there too.

## `token list --with-last-used`: `never` and `unknown` are not the same answer (since v0.88.0)

`--with-last-used` derives each token's most recent activity so you can tell
Expand Down
Loading