superset-cli 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. {superset_cli-0.2.0 → superset_cli-0.3.0}/AGENTS.md +8 -0
  2. {superset_cli-0.2.0 → superset_cli-0.3.0}/PKG-INFO +136 -2
  3. {superset_cli-0.2.0 → superset_cli-0.3.0}/README.md +135 -1
  4. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/architecture/README.md +51 -2
  5. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0010-write-scope-expansion.md +1 -0
  6. superset_cli-0.3.0/docs/decisions/0021-per-invocation-http-timeout.md +35 -0
  7. superset_cli-0.3.0/docs/decisions/0022-explicit-list-query-controls.md +39 -0
  8. superset_cli-0.3.0/docs/decisions/0023-environment-bound-api-keys.md +37 -0
  9. superset_cli-0.3.0/docs/decisions/0024-targeted-cache-controls.md +36 -0
  10. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/README.md +7 -0
  11. superset_cli-0.3.0/docs/plans/2026-06-06-api-key-auth-design.md +40 -0
  12. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-replace-playwright-with-cookie-extraction.md +8 -0
  13. superset_cli-0.3.0/docs/plans/2026-10-06-http-timeout.md +36 -0
  14. superset_cli-0.3.0/docs/plans/2026-10-06-remaining-open-todos.md +84 -0
  15. superset_cli-0.3.0/docs/plans/2026-10-07-cache-help-color-ci.md +32 -0
  16. superset_cli-0.3.0/docs/plans/2026-10-07-complete-open-todos.md +45 -0
  17. superset_cli-0.3.0/docs/tickets/done/2026-06-06-api-key-auth-support.md +26 -0
  18. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-replace-playwright-with-cookie-extraction.md +8 -0
  19. superset_cli-0.3.0/docs/tickets/done/2026-10-06-chart-data-query-selection.md +29 -0
  20. superset_cli-0.3.0/docs/tickets/done/2026-10-06-list-all-pages.md +22 -0
  21. superset_cli-0.3.0/docs/tickets/done/2026-10-06-list-column-selection.md +26 -0
  22. superset_cli-0.3.0/docs/tickets/done/2026-10-06-list-filter-parameters.md +25 -0
  23. superset_cli-0.3.0/docs/tickets/done/2026-10-06-refresh-companion-skill-recipes.md +38 -0
  24. superset_cli-0.3.0/docs/tickets/done/2026-10-06-request-timeout-parameter.md +36 -0
  25. superset_cli-0.3.0/docs/tickets/done/2026-10-07-chart-data-cache-diagnostics.md +31 -0
  26. superset_cli-0.3.0/docs/tickets/done/2026-10-07-chart-data-force-refresh.md +31 -0
  27. superset_cli-0.3.0/docs/tickets/in-progress/2026-10-07-targeted-cache-invalidation.md +56 -0
  28. {superset_cli-0.2.0 → superset_cli-0.3.0}/pyproject.toml +1 -1
  29. superset_cli-0.3.0/src/superset_cli/api_key_auth.py +13 -0
  30. {superset_cli-0.2.0 → superset_cli-0.3.0}/src/superset_cli/cli.py +313 -53
  31. {superset_cli-0.2.0 → superset_cli-0.3.0}/src/superset_cli/client.py +235 -191
  32. {superset_cli-0.2.0 → superset_cli-0.3.0}/src/superset_cli/jwt_auth.py +2 -2
  33. {superset_cli-0.2.0 → superset_cli-0.3.0}/src/superset_cli/models.py +8 -1
  34. superset_cli-0.3.0/tests/test_api_key_auth.py +185 -0
  35. superset_cli-0.3.0/tests/test_cache_controls.py +275 -0
  36. superset_cli-0.3.0/tests/test_list_controls.py +266 -0
  37. superset_cli-0.3.0/tests/test_skill_recipes.py +57 -0
  38. superset_cli-0.3.0/tests/test_timeout.py +106 -0
  39. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_version.py +1 -1
  40. {superset_cli-0.2.0 → superset_cli-0.3.0}/uv.lock +1 -1
  41. superset_cli-0.2.0/docs/plans/2026-06-06-api-key-auth-design.md +0 -110
  42. superset_cli-0.2.0/docs/tickets/in-progress/2026-10-06-refresh-companion-skill-recipes.md +0 -30
  43. superset_cli-0.2.0/docs/tickets/todo/2026-06-06-api-key-auth-support.md +0 -25
  44. {superset_cli-0.2.0 → superset_cli-0.3.0}/.envrc +0 -0
  45. {superset_cli-0.2.0 → superset_cli-0.3.0}/.github/workflows/ci.yml +0 -0
  46. {superset_cli-0.2.0 → superset_cli-0.3.0}/.github/workflows/publish.yml +0 -0
  47. {superset_cli-0.2.0 → superset_cli-0.3.0}/.gitignore +0 -0
  48. {superset_cli-0.2.0 → superset_cli-0.3.0}/LICENSE +0 -0
  49. {superset_cli-0.2.0 → superset_cli-0.3.0}/devenv.lock +0 -0
  50. {superset_cli-0.2.0 → superset_cli-0.3.0}/devenv.nix +0 -0
  51. {superset_cli-0.2.0 → superset_cli-0.3.0}/devenv.yaml +0 -0
  52. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0001-read-only-bootstrap-scope.md +0 -0
  53. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0002-local-config-and-auth-state-storage.md +0 -0
  54. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0003-browser-login-with-playwright-and-saved-storage-state.md +0 -0
  55. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0004-decision-memory-system.md +0 -0
  56. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0005-architecture-reference-document.md +0 -0
  57. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0006-markdown-ticket-system.md +0 -0
  58. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0007-superset-cli-product-and-package-name.md +0 -0
  59. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0008-cookie-extraction-from-installed-browsers.md +0 -0
  60. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0009-write-command-explicit-opt-in.md +0 -0
  61. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0011-custom-api-authentication.md +0 -0
  62. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0011-pypi-release-publishing.md +0 -0
  63. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0012-chart-data-output-contract.md +0 -0
  64. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0013-security-read-scope.md +0 -0
  65. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0014-binary-asset-exports.md +0 -0
  66. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0015-chart-query-overrides.md +0 -0
  67. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0016-api-failure-diagnostics.md +0 -0
  68. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0017-explicit-playwright-auth-export.md +0 -0
  69. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0018-per-instance-jwt-auth.md +0 -0
  70. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0019-default-instance-selection.md +0 -0
  71. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/decisions/0020-guarded-resource-owners.md +0 -0
  72. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/glossary.md +0 -0
  73. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/index.md +0 -0
  74. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-agents-md-design.md +0 -0
  75. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-architecture-doc-maintenance-rule.md +0 -0
  76. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-architecture-overview-doc.md +0 -0
  77. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-architecture-reference-adr.md +0 -0
  78. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-decision-citation-in-final-reporting.md +0 -0
  79. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-decision-memory-for-agents.md +0 -0
  80. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-docs-index-maintenance-rule.md +0 -0
  81. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-docs-index.md +0 -0
  82. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-document-decision-memory-system.md +0 -0
  83. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-plan-decision-follow-up-rule.md +0 -0
  84. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-read-only-next-steps.md +0 -0
  85. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-repository-glossary.md +0 -0
  86. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-reusable-documentation-templates.md +0 -0
  87. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-05-superset-agent-cli-bootstrap.md +0 -0
  88. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-additional-missing-feature-tickets.md +0 -0
  89. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-auth-login-browser-flag.md +0 -0
  90. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-auth-relogin-helper.md +0 -0
  91. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-auth-roadmap-tickets.md +0 -0
  92. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-auth-session-expiry-reporting.md +0 -0
  93. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-auth-ticket-corrections.md +0 -0
  94. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-chart-data-fetch.md +0 -0
  95. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-current-user-and-instance-metadata-reads.md +0 -0
  96. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-dashboard-related-resources.md +0 -0
  97. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-database-schema-and-table-discovery.md +0 -0
  98. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-default-instance-selection.md +0 -0
  99. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-direnv-auto-activation.md +0 -0
  100. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-evaluate-markdown-docs-verification.md +0 -0
  101. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-explore-read-surface-design.md +0 -0
  102. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-github-actions-ci.md +0 -0
  103. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-guest-token-auth-research.md +0 -0
  104. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-jwt-auth-design.md +0 -0
  105. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-list-filtering-and-ordering.md +0 -0
  106. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-markdown-ticket-system.md +0 -0
  107. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-missing-feature-tickets.md +0 -0
  108. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-more-superset-api-gap-tickets.md +0 -0
  109. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-openapi-spec-fetch.md +0 -0
  110. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-phase-1-list-get-resources.md +0 -0
  111. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-phase-2-special-reads.md +0 -0
  112. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-read-only-export-commands.md +0 -0
  113. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-retrospective-feature-tickets.md +0 -0
  114. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-security-read-surface-design.md +0 -0
  115. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-superset-cli-rename.md +0 -0
  116. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-06-write-command-rollout.md +0 -0
  117. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-06-08-dashboard-layout-structure.md +0 -0
  118. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-08-26-csrf-write-requests.md +0 -0
  119. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-08-27-auth-login-auto-fallback.md +0 -0
  120. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-08-27-auth-login-live-validation.md +0 -0
  121. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-10-02-ansi-help-test.md +0 -0
  122. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-10-02-api-command.md +0 -0
  123. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-10-02-artifact-node24.md +0 -0
  124. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-10-02-pypi-release.md +0 -0
  125. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-10-05-public-content-rule.md +0 -0
  126. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-10-06-autonomous-todos-continuation.md +0 -0
  127. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-10-06-autonomous-todos.md +0 -0
  128. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-10-06-ci-colored-output.md +0 -0
  129. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/2026-10-06-owner-management.md +0 -0
  130. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/plans/README.md +0 -0
  131. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/templates/README.md +0 -0
  132. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/templates/decision-record-template.md +0 -0
  133. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/templates/final-report-template.md +0 -0
  134. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/templates/plan-template.md +0 -0
  135. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/README.md +0 -0
  136. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/.gitkeep +0 -0
  137. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-annotation-layer-read-commands.md +0 -0
  138. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-api-key-auth-design.md +0 -0
  139. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-asset-import-write-commands.md +0 -0
  140. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-auth-login-browser-flag.md +0 -0
  141. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-auth-login.md +0 -0
  142. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-auth-logout.md +0 -0
  143. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-auth-path-derivation-helpers.md +0 -0
  144. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-auth-session-expiry-reporting.md +0 -0
  145. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-auth-state-removal-helper.md +0 -0
  146. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-auth-status-inspection-helper.md +0 -0
  147. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-auth-status.md +0 -0
  148. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-auth-validate.md +0 -0
  149. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-base-url-validation-and-normalization.md +0 -0
  150. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-browser-login-persistent-context-flow.md +0 -0
  151. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-chart-data-fetch.md +0 -0
  152. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-chart-write-commands.md +0 -0
  153. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-charts-data-csv-output.md +0 -0
  154. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-charts-data-empty-payload-exit.md +0 -0
  155. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-charts-data-filter-override.md +0 -0
  156. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-charts-get.md +0 -0
  157. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-charts-list.md +0 -0
  158. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-cli-api-error-mapping.md +0 -0
  159. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-cli-entrypoint-delegation.md +0 -0
  160. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-cli-help.md +0 -0
  161. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-cli-instance-resolution-guard.md +0 -0
  162. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-cli-storage-state-guard.md +0 -0
  163. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-config-instance-lookup.md +0 -0
  164. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-config-instance-upsert-and-remove.md +0 -0
  165. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-config-load-and-save.md +0 -0
  166. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-cookie-header-construction.md +0 -0
  167. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-css-template-read-commands.md +0 -0
  168. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-current-user-and-instance-metadata-reads.md +0 -0
  169. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-dashboard-related-resources.md +0 -0
  170. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-dashboard-write-commands.md +0 -0
  171. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-dashboards-get.md +0 -0
  172. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-dashboards-list.md +0 -0
  173. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-database-schema-and-table-discovery.md +0 -0
  174. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-database-write-commands.md +0 -0
  175. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-databases-get.md +0 -0
  176. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-databases-list.md +0 -0
  177. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-dataset-related-objects.md +0 -0
  178. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-dataset-write-commands.md +0 -0
  179. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-datasets-get.md +0 -0
  180. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-datasets-list.md +0 -0
  181. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-datasource-column-value-reads.md +0 -0
  182. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-default-instance-selection-implementation.md +0 -0
  183. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-default-instance-selection.md +0 -0
  184. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-docs-relative-link-check.md +0 -0
  185. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-embedded-dashboard-read-commands.md +0 -0
  186. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-evaluate-markdown-docs-verification.md +0 -0
  187. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-explore-read-commands.md +0 -0
  188. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-explore-read-surface-design.md +0 -0
  189. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-guest-token-auth-research.md +0 -0
  190. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-instances-add.md +0 -0
  191. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-instances-list.md +0 -0
  192. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-instances-remove.md +0 -0
  193. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-jwt-auth-design.md +0 -0
  194. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-jwt-auth-support.md +0 -0
  195. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-list-filtering-and-ordering.md +0 -0
  196. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-logs-and-recent-activity-reads.md +0 -0
  197. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-openapi-spec-fetch.md +0 -0
  198. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-permalink-resolution-reads.md +0 -0
  199. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-query-history-read-commands.md +0 -0
  200. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-read-only-export-commands-implementation.md +0 -0
  201. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-read-only-export-commands.md +0 -0
  202. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-report-schedule-read-commands.md +0 -0
  203. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-saved-queries-read-commands.md +0 -0
  204. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-saved-query-write-commands.md +0 -0
  205. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-security-admin-write-commands.md +0 -0
  206. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-security-read-surface-design.md +0 -0
  207. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-security-rls-read-commands.md +0 -0
  208. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-security-roles-read-commands.md +0 -0
  209. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-security-users-read-commands.md +0 -0
  210. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-sqllab-write-commands.md +0 -0
  211. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-storage-state-loading.md +0 -0
  212. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-superset-client-http-error-mapping.md +0 -0
  213. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-superset-client-lifecycle.md +0 -0
  214. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-superset-client-list-pagination-forwarding.md +0 -0
  215. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-superset-client-pagination-param-builder.md +0 -0
  216. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-superset-client-param-forwarding.md +0 -0
  217. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-superset-client-result-unwrapping.md +0 -0
  218. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-tags-and-themes-write-commands.md +0 -0
  219. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-tags-read-commands.md +0 -0
  220. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-theme-read-commands.md +0 -0
  221. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-06-06-write-scope-expansion-decision.md +0 -0
  222. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-08-26-csrf-write-requests.md +0 -0
  223. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-08-27-auth-login-auto-fallback.md +0 -0
  224. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-08-27-auth-login-live-validation.md +0 -0
  225. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-08-27-session-scoped-cookie-unreadable-from-firefox-zen.md +0 -0
  226. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-actionable-api-errors.md +0 -0
  227. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-chart-owner-add-remove.md +0 -0
  228. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-chart-owner-discovery.md +0 -0
  229. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-chart-owner-replacement.md +0 -0
  230. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-dashboard-owner-add-remove.md +0 -0
  231. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-dashboard-owner-discovery.md +0 -0
  232. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-dashboard-owner-replacement.md +0 -0
  233. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-dashboard-render-verification-recipe.md +0 -0
  234. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-document-api-escape-hatch.md +0 -0
  235. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-playwright-compatible-auth-state.md +0 -0
  236. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/done/2026-10-06-release-capability-preflight.md +0 -0
  237. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/in-progress/.gitkeep +0 -0
  238. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/template.md +0 -0
  239. {superset_cli-0.2.0 → superset_cli-0.3.0}/docs/tickets/todo/.gitkeep +0 -0
  240. {superset_cli-0.2.0 → superset_cli-0.3.0}/scripts/dev-superset-import-snowflake.sh +0 -0
  241. {superset_cli-0.2.0 → superset_cli-0.3.0}/scripts/dev-superset.sh +0 -0
  242. {superset_cli-0.2.0 → superset_cli-0.3.0}/scripts/verify_dashboard.py +0 -0
  243. {superset_cli-0.2.0 → superset_cli-0.3.0}/src/superset_cli/__init__.py +0 -0
  244. {superset_cli-0.2.0 → superset_cli-0.3.0}/src/superset_cli/auth.py +0 -0
  245. {superset_cli-0.2.0 → superset_cli-0.3.0}/src/superset_cli/config.py +0 -0
  246. {superset_cli-0.2.0 → superset_cli-0.3.0}/src/superset_cli/instance_selection.py +0 -0
  247. {superset_cli-0.2.0 → superset_cli-0.3.0}/src/superset_cli/main.py +0 -0
  248. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/conftest.py +0 -0
  249. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/fakes.py +0 -0
  250. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_annotation_layers.py +0 -0
  251. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_api.py +0 -0
  252. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_api_error_details.py +0 -0
  253. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_auth.py +0 -0
  254. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_auth_logout.py +0 -0
  255. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_auth_recovery_guidance.py +0 -0
  256. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_auth_status.py +0 -0
  257. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_auth_validate.py +0 -0
  258. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_chart_data.py +0 -0
  259. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_chart_data_overrides.py +0 -0
  260. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_charts.py +0 -0
  261. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_charts_get.py +0 -0
  262. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_charts_update_clear_qc.py +0 -0
  263. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_cli.py +0 -0
  264. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_client.py +0 -0
  265. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_config.py +0 -0
  266. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_css_templates.py +0 -0
  267. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_dashboard_recipe.py +0 -0
  268. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_dashboards.py +0 -0
  269. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_dashboards_diff.py +0 -0
  270. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_dashboards_get.py +0 -0
  271. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_databases.py +0 -0
  272. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_databases_get.py +0 -0
  273. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_datasets.py +0 -0
  274. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_datasets_get.py +0 -0
  275. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_default_instance.py +0 -0
  276. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_docs_links.py +0 -0
  277. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_exports.py +0 -0
  278. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_instances_add.py +0 -0
  279. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_instances_remove.py +0 -0
  280. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_jwt_auth.py +0 -0
  281. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_logs.py +0 -0
  282. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_me.py +0 -0
  283. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_openapi.py +0 -0
  284. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_owners.py +0 -0
  285. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_phase2_special_reads.py +0 -0
  286. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_playwright_export.py +0 -0
  287. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_queries.py +0 -0
  288. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_release_workflow.py +0 -0
  289. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_repo_files.py +0 -0
  290. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_reports.py +0 -0
  291. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_saved_queries.py +0 -0
  292. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_security_explore_reads.py +0 -0
  293. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_tags.py +0 -0
  294. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_themes.py +0 -0
  295. {superset_cli-0.2.0 → superset_cli-0.3.0}/tests/test_writes.py +0 -0
@@ -82,6 +82,14 @@ For CLI changes:
82
82
  - preserve existing JSON output shape unless the contract is intentionally changed
83
83
  - when changing the contract, update tests and docs in the same task
84
84
 
85
+ ## CLI output and CI verification
86
+
87
+ - Before adding CLI tests, inspect nearby tests and reuse their output normalization and environment setup.
88
+ - Assert semantic help text, not raw terminal output. For Rich/Typer help, normalize with `Text.from_ansi(result.stdout).plain`.
89
+ - Every new help-output test must cover forced-color and no-color environments. Do not disable colors merely to hide failures.
90
+ - Before committing, inspect `.github/workflows/ci.yml` and reproduce relevant CI conditions, including supported Python versions, locked dependencies, and terminal/color settings. Report any untested matrix conditions explicitly.
91
+ - After an authorized push, inspect all CI checks. Report pending or failed checks explicitly; local test success is not CI success.
92
+
85
93
  ## Decision memory rules
86
94
 
87
95
  - Treat `docs/decisions/` as the canonical long-term memory for why this repository works the way it does.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: superset-cli
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: CLI for self-hosted Apache Superset
5
5
  Project-URL: Source, https://github.com/RobinOnHisOwn/superset_cli
6
6
  Project-URL: Issues, https://github.com/RobinOnHisOwn/superset_cli/issues
@@ -32,6 +32,23 @@ Current scope (read by default, write opt-in):
32
32
  - shared list-query controls on all list commands via `--page` (0-based), `--page-size`, `--search`, `--order-column`, and `--order-direction`
33
33
  - user-friendly error messages for auth expiry, missing resources, and network failures (exit code 1, no raw tracebacks)
34
34
 
35
+ ## HTTP timeouts
36
+
37
+ Use the root `--timeout SECONDS` option **before the command** for slow API requests:
38
+
39
+ ```bash
40
+ superset-cli --timeout 90 charts data prod 7 --json
41
+ superset-cli --timeout 90 api prod /api/v1/dashboard/
42
+ ```
43
+
44
+ The default remains 30 seconds. Values must be finite and positive. The option
45
+ applies to API requests, authentication validation/recovery, CSRF acquisition,
46
+ and JWT login/refresh. It controls HTTPX connect/read/write/pool phase or
47
+ inactivity timeouts, **not a total command deadline**. It is not saved in config.
48
+ A timeout exits non-zero; a sent mutation's outcome is unknown. Check server
49
+ state before retrying. The CLI never automatically retries a sent mutation;
50
+ `--allow-write` is still required on every write invocation.
51
+
35
52
  ## Decision log
36
53
 
37
54
  Long-lived technical reasoning lives in `docs/decisions/`.
@@ -58,7 +75,7 @@ superset-cli --help
58
75
 
59
76
  Upgrade with `uv tool upgrade superset-cli`. Python 3.12 or newer is required;
60
77
  uv can provision Python when needed. `pipx install superset-cli` is an alternative.
61
- PyPI `0.1.0` was verified on 2026-10-06: its wheel includes the API command, CSRF handling, validated cookie-import fallback, and `--clear-query-context`, but no `--version` flag. A local installation also labeled `0.1.0` lacked those capabilities; version labels alone are insufficient. This checkout builds distinct **0.2.0** artifacts with `--version`; they have not been published.
78
+ PyPI `0.1.0` was verified on 2026-10-06: its wheel includes the API command, CSRF handling, validated cookie-import fallback, and `--clear-query-context`, but no `--version` flag. A local installation also labeled `0.1.0` lacked those capabilities; version labels alone are insufficient. PyPI **0.2.0** was rechecked on 2026-10-07 and includes `--version`, owners, CSRF handling, and Playwright export. This checkout builds distinct unpublished **0.3.0** artifacts with the new cache controls. An isolated upgrade from 0.1.0 through 0.2.0 to the built 0.3.0 wheel preserved synthetic config/auth files; no publication was performed.
62
79
 
63
80
  Check `command -v superset-cli`, then its installation owner (`uv tool list` or `pipx list`). If it is installed but missing from PATH, use `uv tool update-shell` or `pipx ensurepath` rather than installing another copy. Upgrade with the same tool (`uv tool upgrade superset-cli` or `pipx upgrade superset-cli`). Config/auth files remain separate from the package installation. Check `api --help` and `charts update --help` once per session for required capabilities; use `--version` when available. Inside this source checkout, select `uv run superset-cli` explicitly.
64
81
 
@@ -180,6 +197,72 @@ loopback development (`localhost` or loopback IP literals); embedded URL
180
197
  credentials and malformed bearer values are rejected without echoing secrets.
181
198
  Updating an instance URL preserves its selected auth mode and bindings.
182
199
 
200
+ ## API-key authentication (capability-gated)
201
+
202
+ The source-verified combination is **Superset 6.1.0 with Flask-AppBuilder 5.2.2**,
203
+ `FAB_API_KEY_ENABLED=True`, initialized key storage, an active issued key, and a
204
+ matching prefix. Superset's version alone does not guarantee support. No real
205
+ API-key deployment was exercised during implementation; see [ADR 0023](docs/decisions/0023-environment-bound-api-keys.md).
206
+
207
+ Provide an existing issued key through a secure environment injector, never a
208
+ literal CLI argument or config value. Register only its environment-variable name:
209
+
210
+ ```bash
211
+ superset-cli auth api-key set prod --env EXAMPLE_SUPERSET_API_KEY --json
212
+ superset-cli auth validate prod --json
213
+ superset-cli charts list prod --json
214
+ superset-cli auth api-key clear prod --json
215
+ ```
216
+
217
+ `set` verifies a read-only `/api/v1/me/` request before saving the binding. Use
218
+ `--prefix` if the server's configured prefix differs from `sst_`. The CLI does not
219
+ issue/revoke keys, enable server flags, or upgrade server dependencies. Unsupported
220
+ or rejected authentication fails without saving a binding or browser/JWT fallback.
221
+ Keys are reread from the environment per invocation and never saved in auth files.
222
+ HTTPS is required except loopback HTTP development; redirects and embedded URL
223
+ credentials are rejected. CSRF, timeouts, and per-invocation `--allow-write` remain
224
+ required as applicable; sent mutations never replay. `auth status` reports local
225
+ credential availability, not current server acceptance. `clear` returns to cookie
226
+ mode without deleting cookie/JWT files. Selecting API-key mode replaces prior auth
227
+ bindings; clearing it does not restore JWT credential bindings or the previous mode.
228
+ Reconfigure JWT explicitly when switching back. API keys cannot be exported to Playwright.
229
+
230
+ ## Resource list controls
231
+
232
+ All 15 resource/security lists support optional `--filter`, `--columns`, and `--all`.
233
+ `instances list` is local, not paginated. Ordinary single-page output is unchanged.
234
+
235
+ ```bash
236
+ superset-cli charts list prod --filter '{"col":"viz_type","opr":"eq","value":"table"}' --columns id --columns slice_name --json
237
+ superset-cli logs list prod --filter '{"col":"dttm","opr":"gt","value":"2026-01-01"}' --json
238
+ superset-cli dashboards list prod --all --page-size 100 --json
239
+ ```
240
+
241
+ Repeat JSON-object filters with exactly `col`, `opr`, and `value`. Values retain
242
+ JSON types (strings, numbers, booleans, null, arrays); filters AND together and
243
+ append to `--search`. This is distinct from chart-data `--filter col=value`.
244
+ Resource `_info` determines supported fields/operators; unsupported combinations
245
+ fail rather than using a guessed universal catalog. When a resource omits `_info`
246
+ (as Superset 6.1.0 logs do), the list endpoint validates the filter directly.
247
+ Permission failures never trigger this fallback.
248
+
249
+ Repeat `--columns FIELD` once per unique field. Resource list metadata is checked
250
+ before requesting `q.columns` on the server. Projected human output is compact
251
+ JSON per returned row, so omitted default fields do not produce `None` placeholders.
252
+ Single-page `--json` preserves the server envelope.
253
+
254
+ `--all` starts at page zero, rejects explicit `--page`, and requests 100 records
255
+ per page unless `--page-size` is given. Server caps are respected. Filters,
256
+ projection, and ordering persist across pages; ID ordering is preferred only
257
+ when advertised, otherwise explicit/server ordering is retained. Server `ids`
258
+ allow duplicate checks without adding an unrequested ID field to the projection.
259
+ The aggregate JSON envelope is exactly `{count, ids, result}`. No aggregate is
260
+ printed if a later page fails, counts change, identities duplicate, or pages stop
261
+ early. **This is not an atomic snapshot**: non-unique ordering and concurrent
262
+ changes can still affect completeness even when checks pass. Buffering `--all`
263
+ uses memory proportional to the result. Capability checks add small read requests;
264
+ legacy single-page lists without new controls add none. See [ADR 0022](docs/decisions/0022-explicit-list-query-controls.md).
265
+
183
266
  ## Current commands
184
267
 
185
268
  ```bash
@@ -277,6 +360,57 @@ original saved-chart GET endpoint is used. The chart must have a usable saved
277
360
  uv run superset-cli charts data prod 10 --time-range '2026-04-01 : 2026-05-01' --filter region=west --json
278
361
  ```
279
362
 
363
+ ### Chart cache controls
364
+
365
+ ```bash
366
+ uv run superset-cli charts data prod 10 --cache-info
367
+ uv run superset-cli charts data prod 10 --force --allow-write --json
368
+ uv run superset-cli charts data prod 10 --time-range 'Last week' --filter region=west --force --allow-write --csv
369
+ uv run superset-cli cache invalidate prod --dataset 21 --dataset 22 --allow-write --json
370
+ ```
371
+
372
+ Use discovered numeric IDs; these examples do not authorize live writes.
373
+ `--cache-info` reports each query's server-supplied cache hit/miss, key, timestamp,
374
+ and timeout without extra requests. Missing metadata is unknown, null stays null,
375
+ false means a miss, zero stays zero, and -1 denotes disabled caching. JSON and CSV
376
+ remain unchanged, including errors/empty-result exits. Different native-filter
377
+ combinations can have different cache keys; HTTP success is not freshness proof.
378
+
379
+ `--force` loads the exact requested queries from source and normally replaces
380
+ those cache entries, unless caching is disabled. It does not update saved chart
381
+ configuration or invalidate every dataset/filter combination. Saved-chart GET
382
+ uses `force=true`; copied override POST uses top-level boolean `force`. Because
383
+ force refresh deliberately changes cached state, it requires literal
384
+ `--allow-write` before auth/network access. Ordinary chart reads and non-force
385
+ query overrides retain their existing behavior. Source-verified on Superset 6.1.0;
386
+ unsupported endpoints/contexts fail rather than inventing another transport.
387
+
388
+ `cache invalidate` requires at least one positive numeric SQLA dataset ID; repeat
389
+ `--dataset`, duplicates are removed. UUIDs and implicit all-dataset targets are
390
+ not supported. IDs map to `<ID>__table` datasource UIDs, not dataset UUIDs. The
391
+ target OpenAPI must support `POST /api/v1/cachekey/invalidate` with string
392
+ `datasource_uids`; configured auth, CSRF, and server `CacheRestApi` invalidate
393
+ permissions apply. No service users, keys, or configuration are created.
394
+
395
+ **External prerequisites:** `STORE_CACHE_KEYS_IN_METADATA_DB=True`, tracked keys,
396
+ and compatible cache/data-cache backend, database, and key-prefix configuration.
397
+ Existing untracked entries are not indexed retroactively. Superset 6.1.0 deletes
398
+ through `cache_manager.cache` while chart results use `data_cache`; an incompatible
399
+ setup can remove tracking metadata and return 201 without evicting chart results.
400
+ The endpoint can also log incomplete deletion yet return success. JSON therefore
401
+ reports `{dataset_ids, datasource_uids, accepted, eviction_verified, response}`,
402
+ with `eviction_verified=false`, never invented deletion counts. Human output says
403
+ request accepted, **not verified eviction**.
404
+
405
+ A network failure leaves the outcome unknown; inspect server state before an
406
+ explicit rerun. Sent invalidations never replay automatically. Even a retry's
407
+ success cannot prove eviction after tracking records disappeared. Live acceptance
408
+ requires an explicitly authorized isolated instance: pre-cache multiple filter
409
+ combinations plus an unrelated dataset, invalidate only targets, and verify normal
410
+ non-forced rendered requests stop reusing old target results while unrelated
411
+ cache/session/Celery state stays intact. That live check has not been run. No
412
+ Redis flush or fallback is provided. See [ADR 0024](docs/decisions/0024-targeted-cache-controls.md).
413
+
280
414
  ### Read-only ZIP exports
281
415
 
282
416
  ```bash
@@ -16,6 +16,23 @@ Current scope (read by default, write opt-in):
16
16
  - shared list-query controls on all list commands via `--page` (0-based), `--page-size`, `--search`, `--order-column`, and `--order-direction`
17
17
  - user-friendly error messages for auth expiry, missing resources, and network failures (exit code 1, no raw tracebacks)
18
18
 
19
+ ## HTTP timeouts
20
+
21
+ Use the root `--timeout SECONDS` option **before the command** for slow API requests:
22
+
23
+ ```bash
24
+ superset-cli --timeout 90 charts data prod 7 --json
25
+ superset-cli --timeout 90 api prod /api/v1/dashboard/
26
+ ```
27
+
28
+ The default remains 30 seconds. Values must be finite and positive. The option
29
+ applies to API requests, authentication validation/recovery, CSRF acquisition,
30
+ and JWT login/refresh. It controls HTTPX connect/read/write/pool phase or
31
+ inactivity timeouts, **not a total command deadline**. It is not saved in config.
32
+ A timeout exits non-zero; a sent mutation's outcome is unknown. Check server
33
+ state before retrying. The CLI never automatically retries a sent mutation;
34
+ `--allow-write` is still required on every write invocation.
35
+
19
36
  ## Decision log
20
37
 
21
38
  Long-lived technical reasoning lives in `docs/decisions/`.
@@ -42,7 +59,7 @@ superset-cli --help
42
59
 
43
60
  Upgrade with `uv tool upgrade superset-cli`. Python 3.12 or newer is required;
44
61
  uv can provision Python when needed. `pipx install superset-cli` is an alternative.
45
- PyPI `0.1.0` was verified on 2026-10-06: its wheel includes the API command, CSRF handling, validated cookie-import fallback, and `--clear-query-context`, but no `--version` flag. A local installation also labeled `0.1.0` lacked those capabilities; version labels alone are insufficient. This checkout builds distinct **0.2.0** artifacts with `--version`; they have not been published.
62
+ PyPI `0.1.0` was verified on 2026-10-06: its wheel includes the API command, CSRF handling, validated cookie-import fallback, and `--clear-query-context`, but no `--version` flag. A local installation also labeled `0.1.0` lacked those capabilities; version labels alone are insufficient. PyPI **0.2.0** was rechecked on 2026-10-07 and includes `--version`, owners, CSRF handling, and Playwright export. This checkout builds distinct unpublished **0.3.0** artifacts with the new cache controls. An isolated upgrade from 0.1.0 through 0.2.0 to the built 0.3.0 wheel preserved synthetic config/auth files; no publication was performed.
46
63
 
47
64
  Check `command -v superset-cli`, then its installation owner (`uv tool list` or `pipx list`). If it is installed but missing from PATH, use `uv tool update-shell` or `pipx ensurepath` rather than installing another copy. Upgrade with the same tool (`uv tool upgrade superset-cli` or `pipx upgrade superset-cli`). Config/auth files remain separate from the package installation. Check `api --help` and `charts update --help` once per session for required capabilities; use `--version` when available. Inside this source checkout, select `uv run superset-cli` explicitly.
48
65
 
@@ -164,6 +181,72 @@ loopback development (`localhost` or loopback IP literals); embedded URL
164
181
  credentials and malformed bearer values are rejected without echoing secrets.
165
182
  Updating an instance URL preserves its selected auth mode and bindings.
166
183
 
184
+ ## API-key authentication (capability-gated)
185
+
186
+ The source-verified combination is **Superset 6.1.0 with Flask-AppBuilder 5.2.2**,
187
+ `FAB_API_KEY_ENABLED=True`, initialized key storage, an active issued key, and a
188
+ matching prefix. Superset's version alone does not guarantee support. No real
189
+ API-key deployment was exercised during implementation; see [ADR 0023](docs/decisions/0023-environment-bound-api-keys.md).
190
+
191
+ Provide an existing issued key through a secure environment injector, never a
192
+ literal CLI argument or config value. Register only its environment-variable name:
193
+
194
+ ```bash
195
+ superset-cli auth api-key set prod --env EXAMPLE_SUPERSET_API_KEY --json
196
+ superset-cli auth validate prod --json
197
+ superset-cli charts list prod --json
198
+ superset-cli auth api-key clear prod --json
199
+ ```
200
+
201
+ `set` verifies a read-only `/api/v1/me/` request before saving the binding. Use
202
+ `--prefix` if the server's configured prefix differs from `sst_`. The CLI does not
203
+ issue/revoke keys, enable server flags, or upgrade server dependencies. Unsupported
204
+ or rejected authentication fails without saving a binding or browser/JWT fallback.
205
+ Keys are reread from the environment per invocation and never saved in auth files.
206
+ HTTPS is required except loopback HTTP development; redirects and embedded URL
207
+ credentials are rejected. CSRF, timeouts, and per-invocation `--allow-write` remain
208
+ required as applicable; sent mutations never replay. `auth status` reports local
209
+ credential availability, not current server acceptance. `clear` returns to cookie
210
+ mode without deleting cookie/JWT files. Selecting API-key mode replaces prior auth
211
+ bindings; clearing it does not restore JWT credential bindings or the previous mode.
212
+ Reconfigure JWT explicitly when switching back. API keys cannot be exported to Playwright.
213
+
214
+ ## Resource list controls
215
+
216
+ All 15 resource/security lists support optional `--filter`, `--columns`, and `--all`.
217
+ `instances list` is local, not paginated. Ordinary single-page output is unchanged.
218
+
219
+ ```bash
220
+ superset-cli charts list prod --filter '{"col":"viz_type","opr":"eq","value":"table"}' --columns id --columns slice_name --json
221
+ superset-cli logs list prod --filter '{"col":"dttm","opr":"gt","value":"2026-01-01"}' --json
222
+ superset-cli dashboards list prod --all --page-size 100 --json
223
+ ```
224
+
225
+ Repeat JSON-object filters with exactly `col`, `opr`, and `value`. Values retain
226
+ JSON types (strings, numbers, booleans, null, arrays); filters AND together and
227
+ append to `--search`. This is distinct from chart-data `--filter col=value`.
228
+ Resource `_info` determines supported fields/operators; unsupported combinations
229
+ fail rather than using a guessed universal catalog. When a resource omits `_info`
230
+ (as Superset 6.1.0 logs do), the list endpoint validates the filter directly.
231
+ Permission failures never trigger this fallback.
232
+
233
+ Repeat `--columns FIELD` once per unique field. Resource list metadata is checked
234
+ before requesting `q.columns` on the server. Projected human output is compact
235
+ JSON per returned row, so omitted default fields do not produce `None` placeholders.
236
+ Single-page `--json` preserves the server envelope.
237
+
238
+ `--all` starts at page zero, rejects explicit `--page`, and requests 100 records
239
+ per page unless `--page-size` is given. Server caps are respected. Filters,
240
+ projection, and ordering persist across pages; ID ordering is preferred only
241
+ when advertised, otherwise explicit/server ordering is retained. Server `ids`
242
+ allow duplicate checks without adding an unrequested ID field to the projection.
243
+ The aggregate JSON envelope is exactly `{count, ids, result}`. No aggregate is
244
+ printed if a later page fails, counts change, identities duplicate, or pages stop
245
+ early. **This is not an atomic snapshot**: non-unique ordering and concurrent
246
+ changes can still affect completeness even when checks pass. Buffering `--all`
247
+ uses memory proportional to the result. Capability checks add small read requests;
248
+ legacy single-page lists without new controls add none. See [ADR 0022](docs/decisions/0022-explicit-list-query-controls.md).
249
+
167
250
  ## Current commands
168
251
 
169
252
  ```bash
@@ -261,6 +344,57 @@ original saved-chart GET endpoint is used. The chart must have a usable saved
261
344
  uv run superset-cli charts data prod 10 --time-range '2026-04-01 : 2026-05-01' --filter region=west --json
262
345
  ```
263
346
 
347
+ ### Chart cache controls
348
+
349
+ ```bash
350
+ uv run superset-cli charts data prod 10 --cache-info
351
+ uv run superset-cli charts data prod 10 --force --allow-write --json
352
+ uv run superset-cli charts data prod 10 --time-range 'Last week' --filter region=west --force --allow-write --csv
353
+ uv run superset-cli cache invalidate prod --dataset 21 --dataset 22 --allow-write --json
354
+ ```
355
+
356
+ Use discovered numeric IDs; these examples do not authorize live writes.
357
+ `--cache-info` reports each query's server-supplied cache hit/miss, key, timestamp,
358
+ and timeout without extra requests. Missing metadata is unknown, null stays null,
359
+ false means a miss, zero stays zero, and -1 denotes disabled caching. JSON and CSV
360
+ remain unchanged, including errors/empty-result exits. Different native-filter
361
+ combinations can have different cache keys; HTTP success is not freshness proof.
362
+
363
+ `--force` loads the exact requested queries from source and normally replaces
364
+ those cache entries, unless caching is disabled. It does not update saved chart
365
+ configuration or invalidate every dataset/filter combination. Saved-chart GET
366
+ uses `force=true`; copied override POST uses top-level boolean `force`. Because
367
+ force refresh deliberately changes cached state, it requires literal
368
+ `--allow-write` before auth/network access. Ordinary chart reads and non-force
369
+ query overrides retain their existing behavior. Source-verified on Superset 6.1.0;
370
+ unsupported endpoints/contexts fail rather than inventing another transport.
371
+
372
+ `cache invalidate` requires at least one positive numeric SQLA dataset ID; repeat
373
+ `--dataset`, duplicates are removed. UUIDs and implicit all-dataset targets are
374
+ not supported. IDs map to `<ID>__table` datasource UIDs, not dataset UUIDs. The
375
+ target OpenAPI must support `POST /api/v1/cachekey/invalidate` with string
376
+ `datasource_uids`; configured auth, CSRF, and server `CacheRestApi` invalidate
377
+ permissions apply. No service users, keys, or configuration are created.
378
+
379
+ **External prerequisites:** `STORE_CACHE_KEYS_IN_METADATA_DB=True`, tracked keys,
380
+ and compatible cache/data-cache backend, database, and key-prefix configuration.
381
+ Existing untracked entries are not indexed retroactively. Superset 6.1.0 deletes
382
+ through `cache_manager.cache` while chart results use `data_cache`; an incompatible
383
+ setup can remove tracking metadata and return 201 without evicting chart results.
384
+ The endpoint can also log incomplete deletion yet return success. JSON therefore
385
+ reports `{dataset_ids, datasource_uids, accepted, eviction_verified, response}`,
386
+ with `eviction_verified=false`, never invented deletion counts. Human output says
387
+ request accepted, **not verified eviction**.
388
+
389
+ A network failure leaves the outcome unknown; inspect server state before an
390
+ explicit rerun. Sent invalidations never replay automatically. Even a retry's
391
+ success cannot prove eviction after tracking records disappeared. Live acceptance
392
+ requires an explicitly authorized isolated instance: pre-cache multiple filter
393
+ combinations plus an unrelated dataset, invalidate only targets, and verify normal
394
+ non-forced rendered requests stop reusing old target results while unrelated
395
+ cache/session/Celery state stays intact. That live check has not been run. No
396
+ Redis flush or fallback is provided. See [ADR 0024](docs/decisions/0024-targeted-cache-controls.md).
397
+
264
398
  ### Read-only ZIP exports
265
399
 
266
400
  ```bash
@@ -35,10 +35,57 @@ Typical command flow:
35
35
  2. Typer command registration and command implementations live in `src/superset_cli/cli.py`.
36
36
  3. `src/superset_cli/instance_selection.py` resolves omitted instances before native argument parsing; handlers load configuration through `src/superset_cli/config.py`.
37
37
  4. Cookie login uses `src/superset_cli/auth.py` and `browser-cookie3`, validating candidate state through the current-user API. JWT login/refresh uses `src/superset_cli/jwt_auth.py` with environment-only credentials and separate private token state.
38
- 5. API-backed handlers select browser or JWT state per instance, then construct `src/superset_cli/client.py`'s authenticated client.
38
+ 5. API-backed handlers select cookie/JWT state or an environment-bound API key per instance through `cli.py::_client`, then construct the authenticated `SupersetClient`.
39
39
  6. `SupersetClient` sends REST requests, fetching and caching Superset's CSRF token before writes, and returns JSON payloads.
40
40
  7. `cli.py` formats those payloads for human-readable output or emits compact `--json` output.
41
41
 
42
+ ## Resource list controls
43
+
44
+ All 15 resource/security list callbacks expose `--filter`, `--columns`, and `--all`.
45
+ CLI callbacks validate JSON/field syntax and conflicting page options before
46
+ access. `client.py::build_list_params` composes typed filters with search and
47
+ server-side projection. Every list method delegates to `_list_resource`, which
48
+ checks `_info` filter capabilities separately from list column/order metadata,
49
+ then runs ordinary or checked all-page reads. The all-page envelope is
50
+ `{count, ids, result}`; no partial aggregate is emitted on failure. Projection
51
+ uses server identity metadata without adding fields; `_print_list_projection`
52
+ handles human projected rows. Tests: `tests/test_list_controls.py`. Policy and
53
+ snapshot limitations: [ADR 0022](../decisions/0022-explicit-list-query-controls.md).
54
+
55
+ ## API-key authentication entry point
56
+
57
+ `auth api-key set/clear` manages only environment bindings. `api_key_auth.py`
58
+ reads and validates the key without persisting it. `cli.py::_client` is the shared
59
+ factory for every API-backed handler and selects explicit instance auth settings;
60
+ API-key mode skips saved browser/JWT files. `SupersetClient` applies Bearer auth,
61
+ HTTPS/redirect safety, existing CSRF, and no cookie/JWT recovery for that mode.
62
+ `auth status` reports local availability; `auth validate` performs the acceptance
63
+ read. Tests: `tests/test_api_key_auth.py`. Verified version/configuration limits:
64
+ [ADR 0023](../decisions/0023-environment-bound-api-keys.md).
65
+
66
+ ## Cache control entry points
67
+
68
+ `charts data --force` uses `charts_data` and `SupersetClient.get_chart_data(force=True)`;
69
+ `_require_allow_write` runs before access. Saved reads use GET `force=true`; overrides
70
+ use top-level boolean `force` in the copied context. `--cache-info` formats existing
71
+ response metadata only in human output, preserving JSON/CSV and query exit rules.
72
+
73
+ `cache invalidate` maps to `cli.py::cache_invalidate` and
74
+ `client.py::invalidate_dataset_cache`. It validates numeric targets and the target
75
+ OpenAPI request schema, maps IDs to SQLA datasource UIDs, and reuses `_post`/CSRF
76
+ and the shared auth factory. Acceptance is distinct from verified eviction;
77
+ network outcomes are unknown and no sent write replays. Tests:
78
+ `tests/test_cache_controls.py`. See [ADR 0024](../decisions/0024-targeted-cache-controls.md).
79
+
80
+ ## HTTP timeout entry point
81
+
82
+ The root `--timeout` option is validated in `cli.py` before command execution.
83
+ It sets the context-local `client.py::HTTP_TIMEOUT` and resets it on invocation
84
+ close. `SupersetClient` uses that value for all requests, including auth recovery
85
+ and CSRF acquisition; direct JWT login/refresh clients receive it explicitly.
86
+ `tests/test_timeout.py` covers request metadata, validation, invocation isolation,
87
+ write guards, and unknown mutation outcomes. See [ADR 0021](../decisions/0021-per-invocation-http-timeout.md).
88
+
42
89
  ## Instance/auth entry points
43
90
 
44
91
  - `instances use NAME`, `--show`, `--clear`: `cli.py`, `config.py`, `instance_selection.py`; `tests/test_default_instance.py`.
@@ -57,7 +104,8 @@ Typical command flow:
57
104
  - `src/superset_cli/auth.py` — browser-state paths/inspection, installed-browser cookie import, explicit private Playwright export
58
105
  - `src/superset_cli/jwt_auth.py` — DB/LDAP login/refresh, private separate token state, display-only expiry metadata
59
106
  - `src/superset_cli/instance_selection.py` — default precedence and Typer command arity adapter
60
- - `src/superset_cli/client.py` — cookie/JWT auth selection, bounded GET-only JWT refresh, CSRF-protected API access
107
+ - `src/superset_cli/client.py` — cookie/JWT/API-key transport, bounded GET-only JWT refresh, CSRF-protected API access, checked list traversal
108
+ - `src/superset_cli/api_key_auth.py` — environment-only API-key validation; no state file or key-management API
61
109
  - `scripts/verify_dashboard.py` — optional Playwright rendered-content/tab/screenshot verification (not part of core dependencies)
62
110
  - `tests/` — pytest coverage grouped by command area and helper module
63
111
  - `docs/plans/` — plans and temporary implementation reasoning
@@ -95,6 +143,7 @@ Current command groups:
95
143
  - `saved-queries` (read + write)
96
144
  - `queries`, `logs`
97
145
  - `sqllab` (write-only group: execute, format-sql, estimate, stop-query)
146
+ - `cache` (explicitly targeted tracked-key invalidation; requires `--allow-write`)
98
147
  - `security` (role/user/RLS reads and explicit opt-in writes)
99
148
  - `explore` (saved-chart state and cached form-data reads)
100
149
  - `import` (write-only group: server-side multipart asset bundles)
@@ -20,6 +20,7 @@ Expand the product scope from read-only to "read by default, write opt-in." The
20
20
  - **charts**: create, update, delete, favorite, unfavorite.
21
21
  - **dashboards**: create, update, delete, favorite, unfavorite, copy.
22
22
  - **datasets**: create, update, delete, refresh.
23
+ - **cache controls** (2026-10-07): targeted dataset cache invalidation and explicit chart-result force refresh; see [ADR 0024](0024-targeted-cache-controls.md). No global backend deletion or deployment changes.
23
24
  - **databases**: create, update, delete, test-connection.
24
25
  - **saved-queries**: create, update, delete.
25
26
  - **sqllab**: execute, format-sql, estimate, stop-query.
@@ -0,0 +1,35 @@
1
+ # 0021: Per-invocation HTTP timeout
2
+
3
+ - Status: accepted
4
+ - Date: 2026-10-06
5
+ - Related: [plan](../plans/2026-10-06-http-timeout.md), `src/superset_cli/cli.py`, `src/superset_cli/client.py`, `src/superset_cli/jwt_auth.py`, `tests/test_timeout.py`
6
+
7
+ ## Context
8
+
9
+ Slow chart-data and SQL requests need a longer timeout without replacing the authenticated client or bypassing CSRF handling. Existing commands use 30 seconds. Bounded authentication recovery and no sent-mutation retries remain required by [ADR 0011](0011-custom-api-authentication.md) and [ADR 0018](0018-per-instance-jwt-auth.md).
10
+
11
+ ## Decision
12
+
13
+ Expose one root `--timeout SECONDS` option before the command. Validate finite positive values before browser/network access, retain the 30-second default, and apply the value to every HTTP client created by that invocation, including authentication and CSRF requests.
14
+
15
+ Use HTTPX connect/read/write/pool phase/inactivity timeout semantics, not a total command deadline. A context-local value, reset when the invocation closes, avoids changing every command signature or leaking settings between invocations. Direct JWT clients receive the value explicitly. Do not persist it or add retries.
16
+
17
+ Timeouts exit non-zero with a bounded stderr diagnostic. When the timed-out request was a mutation, report that its outcome is unknown and advise checking server state before retrying. Do not echo exception contents or replay the request.
18
+
19
+ ## Consequences
20
+
21
+ Users can accommodate slow requests while preserving auth handling and write guards. A continuously progressing command can run longer than the timeout. A total deadline would require a separate design. Context-local configuration must be reset even on command failure; tests cover custom/default invocations and request timeout metadata.
22
+
23
+ ## Alternatives considered
24
+
25
+ ### Per-command options
26
+
27
+ Rejected: duplicated declarations and forwarding across dozens of handlers make auth/CSRF coverage easy to miss.
28
+
29
+ ### Persistent instance configuration
30
+
31
+ Rejected: this ticket requests an explicit per-invocation override; persistence hides a previous operator's choice.
32
+
33
+ ### Total runtime deadline or automatic retries
34
+
35
+ Rejected: neither is provided by a scalar HTTPX timeout, and retrying mutations can duplicate writes.
@@ -0,0 +1,39 @@
1
+ # 0022: Explicit server-side list query controls
2
+
3
+ - Status: accepted
4
+ - Date: 2026-10-06
5
+ - Related: [plan](../plans/2026-10-06-remaining-open-todos.md), `src/superset_cli/client.py`, `src/superset_cli/cli.py`, `tests/test_list_controls.py`
6
+
7
+ ## Context
8
+
9
+ Agents currently handwrite API queries for typed filtering, small projections, and complete inventories. FAB exposes resource-specific filter metadata and list column metadata; guessing a universal catalog would reject valid deployments or silently select invalid columns. Some servers cap page size, and concurrent changes can make pagination incomplete.
10
+
11
+ ## Decision
12
+
13
+ Apply the same optional controls to all 15 paginated resource/security lists:
14
+
15
+ - Repeat `--filter '{"col":"viz_type","opr":"eq","value":"table"}'`. Exact object keys and finite JSON values are required before access. Values retain JSON types. Generated `q` serializes literal `+`, `%`, and `&` as JSON Unicode escapes so FAB's extra `parse_qs` decode cannot corrupt them; both ordinary JSON and FAB decoding recover the same values. Filters AND together and append to existing `--search`; chart-data `--filter col=value` remains distinct.
16
+ - Repeat `--columns FIELD`. Require unique non-empty field identifiers. Validate resource support from list metadata, then request `q.columns` on the server. Human projection output is compact JSON per returned record, avoiding invented missing-field placeholders. Ordinary human/JSON output is unchanged without projection.
17
+ - `--all` starts at page zero and rejects explicit `--page`. It defaults to requesting 100 records per page unless a positive `--page-size` is provided; server caps remain authoritative. Preserve filters/projection/order on every page. Prefer ID ordering only if advertised; otherwise preserve explicit or server ordering rather than invent support.
18
+
19
+ Obtain filter/operator capabilities from `_info`; obtain list/order columns from a one-row list metadata request. These are different endpoints. Malformed metadata and permission failures fail closed. If `_info` returns 404 (Superset 6.1.0's log API omits it), send the syntactically valid filter to the list endpoint's native validation instead; never bypass a 403 or guess a field catalog. FAB 5.2.2 advertises datetime `gt`/`lt`, not a universal `ge` operator. No new network calls are added to ordinary single-page lists without these new controls.
20
+
21
+ Emit an aggregate `{count, ids, result}` only after every page passes count, identity, duplicate, and progress checks. Use server `ids` independently of projection, falling back to record IDs when available; do not silently add ID to the requested projection. Later-page failures or inconsistent/empty premature pages exit non-zero without printing a partial aggregate. Single-page JSON retains the raw server envelope.
22
+
23
+ ## Consequences
24
+
25
+ The new controls add small capability reads and buffer an all-page result in memory. Pagination is **not an atomic snapshot**: equal counts and unique IDs cannot detect every concurrent replacement, and non-unique server ordering can still change traversal. Freeze relevant writes or use a server snapshot facility for stronger guarantees; the CLI does not claim one. HTTP timeout/auth/write safety policies remain unchanged.
26
+
27
+ ## Alternatives considered
28
+
29
+ ### Fetch everything and trim locally
30
+
31
+ Rejected: defeats response-size reduction and hides unsupported server projections.
32
+
33
+ ### Resource-independent filter catalog or mandatory ID ordering
34
+
35
+ Rejected: fields/operators/order support vary. Superset 6.1.0 charts do not advertise ID ordering.
36
+
37
+ ### Stream pages directly to stdout
38
+
39
+ Rejected for `--all`: a later failure would leave plausible but incomplete inventory output. Explicit ordinary page calls remain available for streaming clients.
@@ -0,0 +1,37 @@
1
+ # 0023: Environment-bound API keys on verified server capabilities
2
+
3
+ - Status: accepted
4
+ - Date: 2026-10-06
5
+ - Related: [corrected research](../plans/2026-06-06-api-key-auth-design.md), [continuation](../plans/2026-10-06-remaining-open-todos.md), `src/superset_cli/api_key_auth.py`, `tests/test_api_key_auth.py`
6
+
7
+ ## Context
8
+
9
+ API-key authentication is version/configuration dependent. Earlier research examined FAB's abstract manager but missed Superset's inheritance of FAB's concrete SQLA manager. Superset 6.1.0 permits FAB 5.2.2, which implements API-key verification and blueprint registration. This establishes a source-verified combination, not support on every 6.1.0 deployment. No live key or deployment was exercised.
10
+
11
+ ## Decision
12
+
13
+ Add explicit per-instance API-key mode with only an environment-variable binding and configured prefix (default `sst_`). `auth api-key set` requires syntactically valid credentials and successful read-only `/api/v1/me/` authentication before saving the binding. Reject redirects and preserve old config on failed validation. `clear` returns to cookie mode and preserves existing cookie/JWT files. Explicit `set` replaces prior auth bindings, and `clear` does not restore previous JWT bindings or mode; switching back requires explicit JWT configuration.
14
+
15
+ Use a shared CLI client factory for every API-backed handler. Read the key afresh per invocation, enforce bearer syntax and prefix, require HTTPS except loopback HTTP, and reject embedded URL credentials. No auth file is needed or created. Never persist/log the key, fall back to cookies/JWT, retry a sent mutation, issue/revoke keys, or change server flags/dependencies. Existing CSRF handling, HTTP timeouts, and literal per-invocation `--allow-write` apply unchanged.
16
+
17
+ Document the verified combination as Superset 6.1.0 + FAB 5.2.2 with `FAB_API_KEY_ENABLED=True`, initialized key storage, matching prefix, active issued key, and sufficient RBAC. Do not infer capability from the Superset version alone or from Next documentation. CLI binding validation, not a hardcoded version guess, determines acceptance on a target deployment.
18
+
19
+ Status reports local credential availability without implying current server acceptance; `auth validate` performs the live read. API keys cannot substitute for browser state in rendering/export recipes.
20
+
21
+ ## Consequences
22
+
23
+ Operators can use issued keys without browser-cookie extraction or local secret files. The environment must be populated on each invocation. Server-side key creation/revocation and rollout remain operator responsibilities. GET authentication may update server-side key usage bookkeeping; the CLI performs no key-management mutation.
24
+
25
+ ## Alternatives considered
26
+
27
+ ### Persist keys or accept literal key arguments
28
+
29
+ Rejected: exposes secrets in configuration, shell history, process arguments, or logs.
30
+
31
+ ### Treat every Superset 6.1.0 installation as supported
32
+
33
+ Rejected: its FAB dependency range includes versions predating API keys and server enablement/storage vary.
34
+
35
+ ### Block forever because Superset has no direct override
36
+
37
+ Rejected after source verification: the concrete inherited implementation exists. Requiring successful credential validation before binding handles the actual deployment prerequisite without inventing availability.
@@ -0,0 +1,36 @@
1
+ # 0024: Targeted cache controls with truthful acceptance reporting
2
+
3
+ - Status: accepted
4
+ - Date: 2026-10-07
5
+ - Related: [implementation plan](../plans/2026-10-07-complete-open-todos.md), [write guard](0009-write-command-explicit-opt-in.md), [chart output](0012-chart-data-output-contract.md), `tests/test_cache_controls.py`
6
+
7
+ ## Context
8
+
9
+ Operators need fresh chart queries, per-query cache evidence, and targeted dataset invalidation without direct backend access. Superset 6.1.0 implements these surfaces, but invalidation success does not prove chart-result eviction. CacheRestApi deletes through `cache_manager.cache`, whereas chart results use `data_cache`; tracked metadata can be removed even if backend deletion is incomplete.
10
+
11
+ ## Decision
12
+
13
+ Expose the existing server mechanisms only. `charts data --force` uses GET `force=true` for saved-chart reads or top-level boolean `force` in copied override query contexts. It affects every query in that context, not every native-filter combination. Superset bypasses cache reads and normally writes successful results back under their query keys; disabled caching remains disabled. Require literal `--allow-write` before auth/network access for this deliberate cache refresh. Existing non-force reads and ADR 0015 overrides remain unchanged.
14
+
15
+ Opt-in `--cache-info` adds per-query human diagnostics from the existing response: `is_cached`, `cache_key`, `cached_dttm`, and `cache_timeout`. Missing fields are unknown; null, false, zero, and -1 remain distinct. Only -1 denotes disabled caching in the verified contract; zero is reported without inventing its deployment-specific meaning. JSON/CSV output and ADR 0012 exit rules remain unchanged.
16
+
17
+ `cache invalidate INSTANCE --dataset ID [--dataset ID ...] --allow-write` accepts positive numeric dataset IDs, deduplicates them, and maps SQLA datasets to source-verified `<ID>__table` UIDs, not UUIDs. Validate the target's OpenAPI POST request schema for string `datasource_uids`, then reuse configured cookie/JWT/API-key auth and CSRF transport. Server RBAC remains authoritative (`CacheRestApi` invalidate permission); the CLI does not grant permissions or provision credentials. No retry of a sent invalidation.
18
+
19
+ The JSON envelope is `{dataset_ids, datasource_uids, accepted, eviction_verified, response}`. A successful request sets `accepted=true`, `eviction_verified=false`, and preserves the server response, including an empty object for empty 201. Never invent counts or claim eviction. Network failures report unknown outcomes and require inspection before an explicit rerun.
20
+
21
+ ## Consequences
22
+
23
+ Requires external `STORE_CACHE_KEYS_IN_METADATA_DB=True`, tracked entries, and compatible cache/data-cache backend, database, and key-prefix configurations. Previously untracked entries are not retroactively indexed. The CLI cannot infer these conditions from OpenAPI or HTTP success. Live acceptance remains unverified: an explicitly authorized isolated instance must demonstrate multiple normal non-forced filter combinations refresh while unrelated dataset entries and session/Celery state remain intact. No Redis flush/fallback, configuration rollout, service-account provisioning, or orchestration is included.
24
+
25
+ New cache capabilities use unpublished version 0.3.0 because PyPI 0.2.0 was verified as already published. No package is published by this change.
26
+
27
+ ## Alternatives considered
28
+
29
+ - Generic `api` only: retains transport but makes target validation, UID conversion, and truthful acceptance reporting each caller's responsibility.
30
+ - Unguarded force refresh: resembles a read but intentionally changes cached state; explicit invocation permission makes that effect visible.
31
+ - Automatically inspect/delete Redis: bypasses server permissions, risks unrelated data, and still cannot establish rendering freshness. Rejected.
32
+ - Optional CSV query selection: no recurring concrete use case supplied; preserve existing blank-line-separated CSV and raw JSON rather than add another output/exit contract.
33
+
34
+ ## Sources
35
+
36
+ Pinned Superset 6.1.0: [chart-data API](https://github.com/apache/superset/blob/6.1.0/superset/charts/data/api.py), [schemas](https://github.com/apache/superset/blob/6.1.0/superset/charts/schemas.py), [query cache manager](https://github.com/apache/superset/blob/6.1.0/superset/common/utils/query_cache_manager.py), [SQLA UID](https://github.com/apache/superset/blob/6.1.0/superset/connectors/sqla/models.py), [invalidation API](https://github.com/apache/superset/blob/6.1.0/superset/cachekeys/api.py), [invalidation schema](https://github.com/apache/superset/blob/6.1.0/superset/cachekeys/schemas.py), [tracking](https://github.com/apache/superset/blob/6.1.0/superset/utils/cache.py).
@@ -57,6 +57,13 @@ For a copyable starting point, use `../templates/decision-record-template.md`.
57
57
 
58
58
  ## Current decision records
59
59
 
60
+ - [0024: Targeted cache controls](./0024-targeted-cache-controls.md)
61
+
62
+ - [0022: Explicit server-side list query controls](./0022-explicit-list-query-controls.md)
63
+ - [0023: Environment-bound API keys](./0023-environment-bound-api-keys.md)
64
+
65
+ - [0021: Per-invocation HTTP timeout](./0021-per-invocation-http-timeout.md)
66
+
60
67
  - [0010: Write-scope expansion](./0010-write-scope-expansion.md)
61
68
  - [0011: Custom API authentication](./0011-custom-api-authentication.md)
62
69
  - [0012: Chart-data output contract](./0012-chart-data-output-contract.md)