Commit graph

102 commits

Author SHA1 Message Date
ZdenekSrotyr
8e22eed669 Merge branch 'worktree-agent-aaa8db4c' into feature/v2-fastapi-duckdb-docker-cli 2026-04-12 11:15:34 +02:00
ZdenekSrotyr
44317a86c6 merge: resolve factories.py conflict — keep Faker factories + add Block D convenience methods 2026-04-12 11:15:15 +02:00
ZdenekSrotyr
9c2bd3ff25 test: add 132 API gap tests across 8 endpoint modules
Covers upload (sessions, artifacts, local-md), scripts (deploy/run/delete),
settings (get/dataset), memory (CRUD, voting, admin governance),
access-requests (create, approve, deny), permissions (grant/revoke/list),
metadata (get/save/push), and admin configure+registry endpoints.

Each file tests happy path, auth required (401), role enforcement (403),
and input validation (422) independently using the seeded_app fixture.
2026-04-12 11:13:24 +02:00
ZdenekSrotyr
3c653b6dc2 test: add connector test suite (Block D) — 5 files, 58 tests
Tests cover Keboola extractor (extension + legacy fallback, _remote_attach),
BigQuery extractor (remote views, contract validation), Jira service
(webhook processing, HMAC verification, HTTP mocking), Jira incremental
transform (upsert/delete, monthly parquet partitioning), and LLM providers
(factory, AnthropicExtractor retry/auth, OpenAICompatExtractor strategy
cascade, JSON extraction helpers). Also adds tests/helpers/factories.py
with WebhookEventFactory.
2026-04-12 11:12:50 +02:00
ZdenekSrotyr
b6ace1e09a Merge branch 'worktree-agent-af11156d' into feature/v2-fastapi-duckdb-docker-cli 2026-04-12 11:12:14 +02:00
ZdenekSrotyr
5a651ca59c test: add Block C services tests (68 tests across 6 files)
Cover ws_gateway JWT auth, telegram storage user linking and verification
codes, telegram bot handlers, scheduler pure functions, corporate memory
collector hash detection and governance, and session file collection.
2026-04-12 11:11:48 +02:00
ZdenekSrotyr
ba61eb5f44 Merge branch 'worktree-agent-ab9a9016' into feature/v2-fastapi-duckdb-docker-cli 2026-04-12 11:10:27 +02:00
ZdenekSrotyr
4d8de9c3b7 test: add Docker E2E and live connector test files
Adds test_docker_full.py (4 docker-marked tests against a running stack),
test_live_keboola.py, test_live_bigquery.py, and test_live_jira.py (live-marked,
read-only, skipped when credentials are absent).
2026-04-12 11:10:06 +02:00
ZdenekSrotyr
510608813c test: add shared test infrastructure (fixtures, factories, assertions, mocks)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 11:05:35 +02:00
ZdenekSrotyr
e351c38368 test: add correctness test for _reattach_remote_extensions
Verifies that _remote_attach table is actually found via table_catalog
and contains expected extension data (not just resilience).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 08:40:12 +02:00
ZdenekSrotyr
35df940e5c fix: BQ COUNT subquery alias, wrap ImportError in RemoteQueryError
- Add AS _cnt alias to COUNT(*) subquery (BQ Standard SQL requires it)
- Catch ImportError in _get_bq_client() and raise RemoteQueryError
  so API endpoint returns proper 400 instead of 500

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 20:29:03 +02:00
ZdenekSrotyr
77d369e311 fix: CLI help test handles ANSI escape codes in Typer output
Rich/Typer may insert ANSI codes within option names like --register-bq,
breaking exact string matching in CI. Check parts separately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 19:58:01 +02:00
ZdenekSrotyr
2ad8828f8c fix: stdin register_bq parsing, separate BQ SQL validation
- cli/commands/query.py: --stdin mode now reads register_bq from the
  JSON payload and merges it into the register_bq option list, matching
  the documented {"register_bq": {...}, "sql": "..."} contract.
- src/remote_query.py: add _validate_bq_sql() with a narrower blocklist
  (writes only); register_bq() now calls _validate_bq_sql() so legitimate
  BQ operations like INFORMATION_SCHEMA, CALL, IMPORT are not blocked.
  The final DuckDB execute() path still uses the full _validate_sql().
- tests/test_remote_query.py: add TestValidateBqSql covering allowed
  INFORMATION_SCHEMA queries and blocked write operations.
2026-04-11 19:31:39 +02:00
ZdenekSrotyr
f4129dc87d fix: alias validation, url escaping, read-only CLI, blocklist comment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 11:28:27 +02:00
ZdenekSrotyr
ed43feb4e6 feat: add POST /api/query/hybrid endpoint for two-phase BQ+DuckDB queries 2026-04-11 11:09:42 +02:00
ZdenekSrotyr
d605e7d95f feat: add --register-bq and --stdin to da query for hybrid BQ+local queries
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 11:09:11 +02:00
ZdenekSrotyr
86bbb8fce4 feat: add RemoteQueryEngine with BQ registration and safety limits
Two-phase query engine: Phase 1 registers BQ query results as DuckDB
Arrow views (with COUNT pre-check, row/memory limits, Storage API
fallback); Phase 2 executes validated SQL against DuckDB with result
serialization and truncation. 25 tests covering all branches.
2026-04-11 11:07:08 +02:00
ZdenekSrotyr
0a69814fca fix: re-attach remote extensions in get_analytics_db_readonly()
Add _reattach_remote_extensions() helper that reads _remote_attach
tables from attached extract.duckdb files and LOADs the corresponding
DuckDB extensions, so BigQuery and other remote views resolve correctly
in read-only analytics connections.
2026-04-11 11:04:04 +02:00
ZdenekSrotyr
4b4c071959 fix: async httpx in metadata push, guard access_token, add push test
- Replace synchronous httpx.post() with async httpx.AsyncClient in push_metadata_to_source endpoint to avoid blocking the event loop
- Guard data["access_token"] in CLI analyst setup with .get() and a clear error message on missing key
- Add test_push_non_keboola_table_fails and test_push_keboola_table to TestMetadataAPI, covering 400/404 path and the happy path with mocked async httpx
2026-04-11 08:33:10 +02:00
ZdenekSrotyr
126d151413 fix: address code review — path injection, multi-table search, metrics import API, error handling
- Validate view names with _SAFE_IDENTIFIER regex and check path traversal in _initialize_duckdb()
- find_by_table() and get_table_map() now also search the tables[] array field
- Add POST /api/admin/metrics/import endpoint for YAML file upload
- Replace generic except in _connect_to_instance() with specific HTTPStatusError/TimeoutException handlers
- Generate .claude/settings.json in _generate_claude_md() bootstrap
- Update test_find_by_table and test_get_table_map to cover tables[] array lookups
- Add test_import_metrics_yaml in TestMetricsAPI
2026-04-10 19:56:00 +02:00
ZdenekSrotyr
847b48f3af feat: add da analyst status and returning-session freshness check 2026-04-10 19:44:07 +02:00
ZdenekSrotyr
d0cdfcf8c1 feat: add column metadata API with Keboola push support 2026-04-10 19:44:03 +02:00
ZdenekSrotyr
a3531f0ead feat: add da analyst setup command with bootstrap flow 2026-04-10 19:43:36 +02:00
ZdenekSrotyr
89552a00f0 feat: add da admin metadata-show and metadata-apply commands 2026-04-10 19:42:47 +02:00
ZdenekSrotyr
bf90f06774 feat: add ColumnMetadataRepository with CRUD and proposal import 2026-04-10 19:41:53 +02:00
ZdenekSrotyr
488b79f4d1 fix: use SCHEMA_VERSION constant in e2e migration test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:39:19 +02:00
ZdenekSrotyr
344d744089 feat: add 10 starter pack metrics (revenue, usage, sales, operations) 2026-04-10 19:35:28 +02:00
ZdenekSrotyr
5cf0df77fc feat: add Metrics API endpoints (GET/POST/DELETE) with admin auth
- New app/api/metrics.py: GET /api/metrics, GET /api/metrics/{id:path},
  POST /api/admin/metrics (201), DELETE /api/admin/metrics/{id:path}
- Add require_admin dependency to app/auth/dependencies.py
- Register metrics_router in app/main.py before web_router
- Deprecate GET /api/catalog/metrics/{path} with 301 redirect to new endpoint
- 7 new tests in TestMetricsAPI covering CRUD, 404, RBAC, category filter
2026-04-10 19:32:13 +02:00
ZdenekSrotyr
5cddb5573a feat: add da metrics CLI subcommand (list, show, import, export, validate)
Implements Task 4 — five Typer commands under `da metrics`:
- list/show use api_get() to query the server API
- import/export/validate access DuckDB directly via MetricRepository
  and TableRegistryRepository (no server required)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 19:28:51 +02:00
ZdenekSrotyr
a65de8574e feat: add import_from_yaml and export_to_yaml to MetricRepository
Adds YAML-based bulk import/export to MetricRepository, supporting
list-wrapped and plain-dict YAML formats, table→table_name field
mapping, and sql_by_* → sql_variants collection (and reverse on export).
All 24 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 19:25:11 +02:00
ZdenekSrotyr
88d536ca29 feat: add MetricRepository with full CRUD and search for metric_definitions
Implements MetricRepository following the table_registry pattern — raw SQL,
dict returns, ON CONFLICT upsert, and json.dumps for sql_variants/validation.
Includes 18 tests covering create, read, list, update, delete, find_by_table,
find_by_synonym, and get_table_map.
2026-04-10 19:21:25 +02:00
ZdenekSrotyr
cc1445f7ed fix: use SCHEMA_VERSION constant in v3-to-v4 migration test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:18:57 +02:00
ZdenekSrotyr
bc394bd266 feat: schema migration v3→v4 with metric_definitions and column_metadata tables
Add SCHEMA_VERSION = 4, _V3_TO_V4_MIGRATIONS list, and if current < 4 block
in _ensure_schema(). Both new tables are also added to _SYSTEM_SCHEMA for
fresh installs. Tests cover fresh install, all columns, and v3→v4 migration path.
2026-04-10 19:14:32 +02:00
ZdenekSrotyr
6c53082295 feat: multi-instance deployment — all 14 must-have items from spec
CalVer CI (release.yml) with stable/dev channels, health endpoint
with version/channel/schema_version, JWT secret auto-generation with
file persistence, smoke test script + Docker-in-CI, pre-migration
snapshot, /api/admin/configure for headless setup, /api/admin/
discover-and-register, /setup wizard, OpenAPI snapshot test, custom
connector mount support, CHANGELOG, migration safety tests, startup
banner.

663 tests pass (6 new migration safety + 3 OpenAPI snapshot + 1
updated JWT test).
2026-04-10 11:57:42 +02:00
ZdenekSrotyr
cf59abe6dd fix: update tests to provide password after OAuth token bypass fix 2026-04-09 16:35:15 +02:00
ZdenekSrotyr
2043594670 fix: restrict script execution endpoints to analyst/admin roles
deploy, run, and run-deployed require analyst; undeploy requires admin.
Update test to use admin token for undeploy.
2026-04-09 16:31:42 +02:00
ZdenekSrotyr
449053bf8a fix: enforce per-table access control on catalog profile endpoints
Add can_access_table check to GET /api/catalog/profile/{table_name} and
POST /api/catalog/profile/{table_name}/refresh, returning 403 for
unauthorized tables. Update test_api_complete to cover new 403 behaviour
and fix the existing 404 test to use admin token.
2026-04-09 16:30:24 +02:00
ZdenekSrotyr
ad6b3a96e4 fix: enforce role guards on admin web pages
Add require_role(Role.ADMIN) to /admin/tables and /admin/permissions,
and require_role(Role.KM_ADMIN) to /corporate-memory/admin so that
non-admin users receive 403 instead of being served the page.

Fix admin_cookie test fixture to supply a password_hash (required since
the /auth/token endpoint blocks passwordless requests). Add analyst
fixture and TestAdminRoleGuards tests verifying analysts get 403 and
admins get 200 on the protected routes.
2026-04-09 16:30:13 +02:00
ZdenekSrotyr
3205a8d300 fix: block /auth/token for OAuth-only users without password_hash
Users without a password_hash (Google OAuth / magic-link accounts) could
obtain a JWT by simply posting their email to /auth/token. Add an else
clause that rejects such requests with 401, directing them to their
configured auth provider. Update and extend tests accordingly.
2026-04-09 16:29:47 +02:00
ZdenekSrotyr
55515266ea fix: block DuckDB metadata functions and relative paths in query endpoint
Add information_schema, duckdb_* introspection functions, pragma_* functions,
and relative path traversal patterns to the SQL blocklist so users cannot
enumerate schema metadata regardless of RBAC. Add six corresponding tests.
2026-04-09 16:29:11 +02:00
ZdenekSrotyr
afa84f6585 fix: web UI smoke tests — reset DuckDB singleton, get token via API 2026-04-09 07:18:17 +02:00
ZdenekSrotyr
5131816a5b test: add missing coverage for web UI, Jira extract, instance config, and concurrent rebuild
- tests/test_web_ui.py: smoke tests for all authenticated web pages (login, dashboard, catalog, corporate-memory, activity-center, admin/tables, admin/permissions)
- tests/test_jira_service.py: unit tests for extract_init and update_meta in the Jira connector
- tests/test_instance_config.py: verifies get_instance_name() returns a string when config file is absent
- tests/test_orchestrator.py: concurrent rebuild test asserting rebuild succeeds while a read-only connection holds the analytics DB
2026-04-09 07:15:14 +02:00
ZdenekSrotyr
8df8183a9f feat: add 50 MB upload size limit to session and artifact endpoints
Rejects files exceeding MAX_UPLOAD_SIZE with HTTP 413 before writing to disk.
2026-04-09 07:14:16 +02:00
ZdenekSrotyr
8e9a0c367a fix: replace os.environ direct assignment with monkeypatch.setenv in test fixtures
Prevents environment variable leaking between tests. All DATA_DIR,
JWT_SECRET_KEY, and SCRIPT_TIMEOUT assignments in fixtures now use
monkeypatch.setenv() which auto-reverts after each test. Removes
manual os.environ.pop() cleanup lines.
2026-04-09 07:11:36 +02:00
ZdenekSrotyr
53a9e838f9 feat: add graceful shutdown handler
- Add close_system_db() function in src/db.py to cleanly close shared DB connection
- Add lifespan context manager in app/main.py to trigger shutdown on app exit
- Integrate lifespan into FastAPI app initialization
- All API tests pass (77/77)
2026-04-09 07:03:45 +02:00
ZdenekSrotyr
1b3acce7e9 fix: replace substring table access check with word-boundary regex
Replace substring matching with word-boundary regex in query endpoint's
table access validation. Prevents false positives where short table names
like 'id' would block any query containing the word. Uses re.escape() to
safely handle special characters in table names.

- Import re module at top
- Use regex pattern with word boundaries (\b) for matching
- Add tests to verify no false positives and proper blocking
2026-04-09 07:00:48 +02:00
ZdenekSrotyr
3e9c347cf1 fix: validate extract dir name in get_analytics_db_readonly to prevent SQL injection
Adds _SAFE_IDENTIFIER regex guard before ATTACHing extract.duckdb files in the
read-only analytics connection, matching the same fix already applied in the
orchestrator. Adds test coverage for malicious directory names.
2026-04-09 06:57:31 +02:00
ZdenekSrotyr
e425d4baa5 fix: handle WAL files in atomic swap to prevent DB corruption
Add _atomic_swap_db helper that removes stale WAL files before and after
moving the temp DuckDB into place. Apply CHECKPOINT before close in both
orchestrator and Keboola extractor so DuckDB flushes WAL before the swap.
2026-04-09 06:57:29 +02:00
ZdenekSrotyr
3321d2e266 security: reduce JWT expiry to 24h and add jti claim
Tokens previously lasted 30 days with no revocation path. Expiry is now
24 hours and every token carries a unique jti (UUID hex) to support future
revocation checks.
2026-04-09 06:57:23 +02:00
ZdenekSrotyr
23ae6a602c security: harden query endpoint SQL blocklist and disable external access
Expand blocked keywords to cover parquet_scan, read_csv_auto, query_table,
iceberg_scan, delta_scan, call, URL schemes (http/https/s3/gcs), and
additional file-scan functions. Set enable_external_access=false on the
non-read-only analytics connection path. Add three new tests covering
parquet_scan, read_csv_auto, and query_table blocking.
2026-04-09 06:54:58 +02:00