Commit graph

785 commits

Author SHA1 Message Date
ZdenekSrotyr
10d7bd62f8 fix(bq): #160 wrap views via bigquery_query() for VIEW/MATERIALIZED_VIEW
Issue #160: da query --remote against query_mode='remote' BQ rows whose
underlying entity is a VIEW or MATERIALIZED_VIEW returned a DuckDB catalog
error because the extractor (with legacy_wrap_views=False default since
the v2 fetch primitives release) skipped master-view creation for those
entity types — but kept inserting the _meta row, leaving operators with a
registered name that resolves to nothing.

Always create a master view for entity types we have proven runtime support
for in this codebase:

  BASE TABLE          → bq."<dataset>"."<source_table>"
                        (Storage Read API path; predicate pushdown)
  VIEW / MAT_VIEW     → bigquery_query('<project>', 'SELECT * FROM `proj.ds.tbl`')
                        (jobs API path; no pushdown — the upcoming /api/query
                        cost guardrail bounds the scan; was the legacy
                        legacy_wrap_views=True branch SQL form, just always-on)

For other entity types (EXTERNAL, SNAPSHOT, CLONE, future), log a warning
and SKIP both the master view AND the _meta row. The registry row remains
intact so /api/v2/scan still works for `da fetch`; we just don't expose a
stale _meta entry that the orchestrator would later strand.

The legacy_wrap_views config knob is still readable in this commit (read
returns the value, which is then ignored). Removal across the rest of
the codebase happens in the follow-up REFACTOR commit.

tests/test_bigquery_extractor.py:
- Add 3 RED tests covering the new always-wrap behavior:
  test_view_creates_wrap_view_with_default_config,
  test_materialized_view_creates_wrap_view_with_default_config,
  test_unsupported_entity_type_skips_meta_and_view.
- Fix pre-existing flakiness in test_main_exits_when_project_missing
  by resetting app.instance_config cache before the no-project mock —
  the prior test populates the cache with a project, and removing the
  legacy_wrap_views get_value() call surfaced this latent ordering bug.
2026-05-04 10:31:35 +02:00
ZdenekSrotyr
4aa96f2546 docs(specs): #160 implementation spec for da query --remote VIEW fix
Spec for the upcoming fix: when query_mode='remote' BigQuery rows have a
VIEW or MATERIALIZED_VIEW entity, da query --remote currently fails with
DuckDB catalog error because the extractor (with legacy_wrap_views=False
default) skips master view creation for those entity types.

Plan:
- always create master view (Storage Read API for BASE TABLE; jobs API
  via bigquery_query() for VIEW/MATERIALIZED_VIEW); remove the
  legacy_wrap_views config knob entirely
- add server-side cost guardrail on /api/query (5 GiB default cap,
  per-user daily-byte + concurrent-slot quota shared with /api/v2/scan)
- close pre-existing RBAC hole on direct bq."ds"."tbl" references
  (registry-gated; admin must register first)
- add bigquery_query() to SQL blocklist (closes function-call backdoor)
- shared CLI structured-error renderer (cli/error_render.py) so typed
  BqAccessError details render readably instead of raw JSON dumps
- /admin/server-config: BQ "Test connection" button + placeholder for
  billing_project showing the resolved fallback to data project

TDD plan in 6 phases / 11 commits — see spec section 6.
2026-05-04 10:31:35 +02:00
ZdenekSrotyr
b7e6ae1559
Merge pull request #170 from keboola/zs/setup-summary-fix
fix(cli): setup summary reflects actual CLAUDE.md outcome
2026-05-04 07:24:30 +02:00
ZdenekSrotyr
68b9fca3cc docs(changelog): note CLAUDE.md write-outcome summary fix in [0.31.0] 2026-05-04 07:20:56 +02:00
ZdenekSrotyr
297d07f2a1 fix(cli): setup summary reflects actual CLAUDE.md write outcome (True/False return) 2026-05-04 07:17:37 +02:00
ZdenekSrotyr
c0aa278c67
Merge pull request #169 from keboola/zs/agent-workspace-prompt
feat: Agent Setup Prompt + Workspace Prompt — admin-editable bash setup script + CLAUDE.md (combined)
2026-05-04 07:14:27 +02:00
ZdenekSrotyr
83b2fe4e9c docs(claude-md): bump documented schema v22 → v23 (claude_md_template) 2026-05-04 07:05:35 +02:00
ZdenekSrotyr
95bf420af3 release(0.31.0): cut Agent Setup Prompt + Agent Workspace Prompt 2026-05-04 07:04:43 +02:00
ZdenekSrotyr
8cb6fdc546 fix(claude_md): load default via importlib.resources — survives /app/config bind-mount 2026-05-04 06:53:47 +02:00
ZdenekSrotyr
93fdea3461 fix(claude_md): RBAC-filter tables; align today with now (UTC)
- _list_tables now accepts a user param and delegates to
  get_accessible_tables: admins see all, non-admins see only tables
  covered by their resource_grants. Fixes silent leak of table names
  to unauthorised analysts.
- today derived from now.date() (UTC) instead of date.today()
  (server-local TZ), so today and now are always consistent.
- Updated test_render_override_tables_list to seed an admin user so
  RBAC filtering doesn't hide the table; added three new tests covering
  per-user table isolation, admin sees-all, and no-grants-empty.
2026-05-04 05:57:22 +02:00
ZdenekSrotyr
a2157ee807 fix(claude_md): restore full default content (BQ cost guard, hybrid example, ad-hoc table, deeper guidance) 2026-05-04 05:48:04 +02:00
ZdenekSrotyr
65e39a087d docs+tests: Agent Workspace Prompt + drop stale BREAKING markers
- CHANGELOG.md: add Agent Workspace Prompt bullets under [Unreleased]; remove
  stale BREAKING (CLI) and BREAKING (API) bullets about CLAUDE.md removal and
  GET /api/welcome deletion — both behaviors are restored in this PR; replace
  with a neutral Changed bullet describing da analyst setup writing CLAUDE.md
- docs/agent-workspace-prompt.md: operator reference for the feature (when
  written, editing via UI/API, template language, full placeholder table,
  Jinja2 examples, reset to default)
2026-05-03 22:44:22 +02:00
ZdenekSrotyr
955b56608d feat(api,web,cli): /admin/workspace-prompt + /api/welcome restored + da analyst writes CLAUDE.md
- app/api/claude_md.py: GET /api/welcome (analyst, auth required); GET/PUT/DELETE
  /api/admin/workspace-prompt-template; POST …/preview; two-pass Jinja2 validation
  on PUT; validation stub mirrors build_claude_md_context() shape
- app/main.py: register claude_md_router
- app/web/router.py: GET /admin/workspace-prompt → admin_workspace_prompt.html
- app/web/templates/admin_workspace_prompt.html: CodeMirror editor + live preview +
  status chip + reset modal; mirrors admin_welcome.html for Agent Setup Prompt
- app/web/templates/_app_header.html: add "Agent Workspace Prompt" nav item next to
  "Agent Setup Prompt"; extend _admin_active to cover /admin/workspace-prompt
- cli/commands/analyst.py: _init_claude_workspace now accepts server_url + token;
  _write_claude_md fetches GET /api/welcome, writes CLAUDE.md, graceful 404/5xx;
  setup command adds --no-claude-md flag to opt out; default = write CLAUDE.md
- tests: test_claude_md_api.py (16 tests); test_analyst_bootstrap.py updated with
  4 new CLAUDE.md bootstrap tests; test_welcome_template_api.py: update stale
  assertion about /api/welcome being removed (endpoint restored)
- tests/snapshots/openapi.json: regenerated
2026-05-03 22:44:14 +02:00
ZdenekSrotyr
f01eb4143d feat(db,repo,renderer): schema v23 + claude_md_template + ClaudeMd renderer
- Bump SCHEMA_VERSION 22 → 23; add claude_md_template singleton table to
  _SYSTEM_SCHEMA and _V22_TO_V23_MIGRATIONS; wire migration + fresh-install seed
- src/repositories/claude_md_template.py: ClaudeMdTemplateRepository (get/set/reset)
  mirroring WelcomeTemplateRepository; defensive re-seed in get()
- src/claude_md.py: compute_default_claude_md / render_claude_md /
  build_claude_md_context — rich renderer with RBAC-filtered tables, metrics,
  and marketplaces; reads override from claude_md_template or falls back to
  config/claude_md_template.txt; raises TemplateError on broken override
- config/claude_md_template.txt: default Jinja2 markdown template restored from
  PR #167 history (tables, metrics, marketplaces, BQ guidance, corporate memory,
  directory structure, per-user footer)
2026-05-03 22:43:56 +02:00
ZdenekSrotyr
53f841f244 release(undo): un-cut 0.31.0 — re-cut once Workspace Prompt feature also lands 2026-05-03 22:27:22 +02:00
ZdenekSrotyr
1d271eea56
Merge pull request #167 from keboola/zs/welcome-prompt
feat: customizable Agent Setup Prompt — admin-editable bash bootstrap on /setup
2026-05-03 22:10:42 +02:00
ZdenekSrotyr
9ad7856f72 fix(devin-review): dashboard CTA respects override; PUT validates anon path
Finding #1: _build_context now routes through render_agent_prompt_banner when
a DB connection is available, so both /setup and the /dashboard clipboard CTA
always reflect the admin override (or the live default when no override is set).
Previously _build_context unconditionally used resolve_lines(), ignoring the
welcome_template override for the dashboard JS array.

Finding #2: PUT /api/admin/welcome-template now performs a second render pass
with user=None (anonymous stub) after the authenticated-user pass. Templates
that reference user.* fields without an {% if user %} guard are rejected with
a clear 400 error explaining the anon-visitor breakage.
2026-05-03 21:45:32 +02:00
ZdenekSrotyr
d18bc4c8f7 fix(api): align PUT validation autoescape with runtime (False); docs match 2026-05-03 21:30:24 +02:00
ZdenekSrotyr
7bbf9413a6 docs(claude-md): bump documented schema version v20 → v22 (welcome_template + setup_banner) 2026-05-03 21:27:16 +02:00
ZdenekSrotyr
61ef0d0eed fix(devin-review): address 4 findings on PR #167
- Fix #1: _detect_existing_project now checks .claude/settings.json for
  "da sync" marker instead of deleted CLAUDE.md; update tests accordingly.
- Fix #2: preview endpoint uses autoescape=False to match /setup rendering;
  align render_agent_prompt_banner in welcome_template.py to the same.
- Fix #3: apply _sanitize_banner_html to override render path in setup_page
  so all render paths sanitize consistently.
- Fix #4: move .setup-link-banner into the existing-user branch where
  account_details.last_sync_display is reachable; remove dead copy from
  new-user branch.
2026-05-03 21:15:01 +02:00
ZdenekSrotyr
26dc367037 release(0.31.0): cut Agent Setup Prompt + BREAKING CLI/API removals 2026-05-03 21:03:57 +02:00
ZdenekSrotyr
bcb62ff4e2 fix(ui): tighten dashboard token row gap; lift editor/preview labels above panes 2026-05-03 19:51:34 +02:00
ZdenekSrotyr
97e72c3f1c test(web-ui): update dashboard CTA link assertion after copy edit 2026-05-03 19:35:59 +02:00
ZdenekSrotyr
05f12b416d fix(ui): dashboard token row alignment + match editor/preview heights 2026-05-03 19:23:50 +02:00
ZdenekSrotyr
dc931a6556 feat(admin-prompt): default = live setup script; override replaces /setup content
The /admin/agent-prompt editor now pre-fills with the full bash bootstrap
script from setup_instructions.resolve_lines() instead of being empty.
When an admin saves an override it replaces the default everywhere — the
/setup page display and the dashboard clipboard CTA — rather than adding a
banner above the auto-generated commands.

GET /api/admin/welcome-template now returns a `default` field with the live
computed script so the editor always shows meaningful starting content.

{server_url} and {token} single-brace placeholders survive Jinja2 rendering
and are substituted by JavaScript at clipboard-copy time as before.

Preview pane switches to textContent (not innerHTML) since content is bash.
2026-05-03 16:31:35 +02:00
ZdenekSrotyr
d7705b5aa3 chore(openapi): regenerate snapshot after /api/welcome removal 2026-05-03 16:12:13 +02:00
ZdenekSrotyr
8f71af6c22 docs(changelog): variant C — banner-on-setup model
Update [Unreleased] to reflect the actual shipped behavior:
- banner on /setup replaces CLAUDE.md generation
- BREAKING: da analyst setup no longer writes CLAUDE.md
- BREAKING: GET /api/welcome removed
- schema v21/v22 notes corrected
- drop sync_interval bullet (not part of this feature set)
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
c4d23cf235 feat(admin-prompt): update editor UX + docs for banner context
- admin_welcome.html: update subtitle, description, placeholder cheatsheet
  (drop tables/metrics/marketplaces/sync_interval; add user-null note and
  security note). Textarea initial value is now empty (no default template
  to show). Preview pane uses innerHTML (HTML output). refreshStatus sets
  editor to empty when no override. Preview pane styled as light surface.
  Reset modal copy updated (no banner shown, not "OSS-shipped template").
- config/claude_md_template.txt: deleted (markdown template is gone;
  default is now no banner).
- docs/agent-setup-prompt.md: rewritten for variant C — describes the
  /setup banner, smaller placeholder table, security/sanitization notes,
  anonymous-user guard, example HTML snippet.
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
8db4c1645b feat(admin-prompt): variant C — banner on /setup, drop CLAUDE.md generation
- src/welcome_template.py: rewrite as HTML banner renderer
  (render_agent_prompt_banner); drop _list_tables, _metrics_summary,
  _marketplaces_for_user, render_welcome, _load_default_template.
  build_context now exposes only instance/server/user/now/today.
  _sanitize_banner_html strips script/iframe/on*/javascript: post-render.
- app/api/welcome.py: drop get_welcome handler, WelcomeResponse, old
  _VALIDATION_STUB_CONTEXT. Admin endpoints stay at same URLs; validation
  stub updated to match new slim context. Preview now uses autoescape=True.
- app/web/router.py: setup_page calls render_agent_prompt_banner and passes
  banner_html to install.html; admin_agent_prompt_page drops _load_default_template.
- app/web/templates/install.html: add .setup-banner CSS + banner block above hero.
- cli/commands/analyst.py: replace _generate_claude_md with _init_claude_workspace;
  no CLAUDE.md written, only .claude/CLAUDE.local.md placeholder + settings.json hooks.
- tests: delete test_cli_analyst_welcome.py (tests deleted endpoint/function);
  rewrite TestGenerateClaudeMd → TestInitClaudeWorkspace; update api test to
  assert /api/welcome returns 404 and remove welcome-fetch tests.
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
60386b9c3c polish: drop dead CSS, fix docstring drift, add agent-prompt route test 2026-05-03 16:12:13 +02:00
ZdenekSrotyr
ecb6c35ad5 feat(admin): rename /admin/welcome to /admin/agent-prompt (Agent Setup Prompt)
Rename the welcome prompt editor from /admin/welcome to /admin/agent-prompt
and update all UI labels to "Agent Setup Prompt". API endpoint URLs are
unchanged (PUT/GET/DELETE /api/admin/welcome-template, GET /api/welcome).

- Nav menu: "Welcome prompt" → "Agent Setup Prompt", href updated
- Page title and h2 updated in admin_welcome.html
- Error message hint in app/api/welcome.py updated to /admin/agent-prompt
- Dashboard: replace inline <details> preview of _claude_setup_instructions
  with a simple link to /setup (Task C)
- docs/welcome-template.md renamed to docs/agent-setup-prompt.md; internal
  references to /admin/welcome updated
- OpenAPI snapshot path updated
- Tests updated to reflect new route and removed inline preview
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
c7b14fb120 feat(admin): drop setup_banner feature; consolidate into single editor
Remove the setup_banner feature (admin-editable /setup page banner) and
all associated code: API router, repository, renderer, admin template,
tests, and docs. The setup_page handler no longer calls render_setup_banner;
the install.html template no longer renders banner_html. The setup_banner
DuckDB table (v22) is kept intact for forward-compat with already-migrated
instances — only the application code is removed.

CHANGELOG updated: setup_banner bullets removed; Agent Setup Prompt
(welcome-template feature) now stands alone as the single editable prompt.
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
0ee22f8fb0 docs: add setup-banner.md + rename migration test to test_db_schema_version.py
- Add docs/setup-banner.md: placeholder table, autoescape semantics, security
  note on post-render stripping, diff table vs welcome-template (M-9).
- Update CHANGELOG.md to reference docs/setup-banner.md.
- Rename tests/test_db_migration_v20.py → tests/test_db_schema_version.py
  (file tested SCHEMA_VERSION==22, not just the v20 step; clearer name) (M-10).
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
5bfd8997ea test: RBAC marketplace render test + validation stub drift detectors
- test_render_marketplaces_filtered_by_rbac: seeds 2 marketplaces, 2 groups,
  grants, 2 users; asserts each user's rendered output references only their
  group's marketplace/plugins, not the other's (I-3).
- test_validation_stub_matches_build_context_shape in test_welcome_template_api.py:
  asserts _VALIDATION_STUB_CONTEXT top-level and nested keys (instance, server,
  user) match build_context() output so stub drift is caught in CI (I-4).
- test_validation_stub_matches_build_context_shape in test_setup_banner_api.py:
  same shape check against build_setup_banner_context() (I-4).
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
b3ffc98e9f fix(security): XSS hardening for setup banner + cleanup unused imports
- Add _sanitize_banner_html() to src/setup_banner.py: strips <script>/
  <iframe> blocks, on* event-handler attributes, and javascript:/data:
  URI schemes post-render (I-2). Defense-in-depth — /setup is partly
  anonymous so malformed admin content must not execute in visitors'
  browsers.
- Apply sanitizer in render_setup_banner() before returning rendered HTML.
- Add 3 unit tests: test_render_strips_script_tags,
  test_render_strips_event_handlers, test_render_strips_javascript_uri.
- Drop unused Optional import from src/repositories/welcome_template.py
  and src/repositories/setup_banner.py (M-6).
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
b0ec842804 feat(admin-ui): SRI + CDN fallback for CodeMirror, 301→302 on /install, error sanitization
- Add integrity= + crossorigin= to all 4 cdnjs tags in admin_welcome.html
  and admin_setup_banner.html (I-1)
- Add graceful CDN fallback: when CodeMirror is undefined (SRI mismatch or
  CDN down), degrade to styled plain textarea with polyfill editor interface
  so save/reset/preview still work (I-1)
- Replace fixed 480px editor height with calc(100vh - 320px) for
  viewport-relative sizing; add min-height: 480px to .welcome-editor-col (M-8)
- Change /install redirect from 301 to 302 to prevent indefinite browser
  caching (I-5)
- Sanitize Jinja2 error detail in /api/welcome 500 response: log full error
  server-side, return generic detail pointing at /admin/welcome (M-7)
- Hoist build_context import to module level in app/api/welcome.py (M-11)
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
8ec194cbe4 test(db): bump v20 migration test assertions to v22 2026-05-03 16:12:13 +02:00
ZdenekSrotyr
39146288e1 feat: admin-editable setup_banner on /setup page (schema v22)
Adds an optional Jinja2/HTML banner displayed above the bootstrap
commands on /setup. Empty by default; admin authors it at
/admin/setup-banner. autoescape=True — safe for HTML context.
Render failures return "" so a broken banner never breaks /setup.

Schema v22: setup_banner singleton table, auto-migration v21→v22.
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
40d221f20a feat(admin-welcome): CodeMirror editor + live preview pane 2026-05-03 16:12:13 +02:00
ZdenekSrotyr
4bcdc4e7d7 feat(dashboard): link Claude Code setup CTA to /setup page 2026-05-03 16:12:13 +02:00
ZdenekSrotyr
85967e14ca feat(web): rename /install → /setup; nav label 'Setup local agent'
- Add GET /setup serving install.html (CLI + Claude Code setup page)
- Add GET /install → 301 redirect to /setup for backwards compat
- Move first-time setup wizard from /setup to /first-time-setup
- Update nav link: href=/setup, label 'Setup local agent', active on both /setup and /install paths
- Update page <title> to 'Setup local agent — …'
- Update /dashboard and /setup comment in _claude_setup_instructions.jinja
- Update tests and OpenAPI snapshot accordingly
2026-05-03 16:12:13 +02:00
ZdenekSrotyr
92fd78cfb4 fix(admin-welcome): redesign with peer chrome, toast, btn-copy 2026-05-03 16:12:13 +02:00
ZdenekSrotyr
1eb03405c7 test(db): bump v20 migration test assertions to v21 2026-05-03 16:12:13 +02:00
ZdenekSrotyr
b579f119b5 docs(changelog): customizable welcome prompt 2026-05-03 16:12:13 +02:00
ZdenekSrotyr
1c07977d84 docs: welcome-template customization reference 2026-05-03 16:10:48 +02:00
ZdenekSrotyr
517e63d217 fix(cli): warn on welcome-fetch failures; expand test coverage 2026-05-03 16:10:48 +02:00
ZdenekSrotyr
c604dad9cf feat(cli): da analyst setup fetches rendered welcome from /api/welcome 2026-05-03 16:10:48 +02:00
ZdenekSrotyr
ecaa113c68 fix(admin-welcome): credentials: include, real-content preview, refresh after mutate 2026-05-03 16:10:48 +02:00
ZdenekSrotyr
2b3048f77f feat(web): /admin/welcome editor page 2026-05-03 16:10:48 +02:00
ZdenekSrotyr
93b713900b fix(api): validate template render on PUT; broaden render-time catch 2026-05-03 16:10:48 +02:00