Commit graph

96 commits

Author SHA1 Message Date
Claude
194ee95ae2
Merge remote-tracking branch 'origin/main' into claude/json-api-docs-1-0-review-a3e83u
# Conflicts:
#	datasette/__init__.py
#	tests/test_api_write.py
2026-07-06 22:25:27 +00:00
Claude
3a0ea58557
Unify page-size parameters on _size with table semantics
The stored query lists silently clamped out-of-range ?_size= values
(a request for 5000 quietly returned 1000) and did not accept the max
keyword. They now share the table view semantics via a new
parse_size_limit() helper: blank means default, "max" means the
maximum (max_returned_rows for query lists), negative or non-integer
values are a 400, and values over the maximum are a 400 instead of
being silently clamped.

The /-/allowed and /-/rules debug endpoints renamed their bare
page/page_size parameters to _page/_size, matching the underscore
grammar used by every other system parameter, with the same validation
(400 instead of silently capping page_size at 200). Their HTML debug
pages and next_url/previous_url builders use the new names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
2026-07-04 17:54:03 +00:00
Claude
404ee4c3a7
Document the JSON API stability promise
docs/json_api.rst now opens with an API stability section declaring
what the 1.x promise covers: documented endpoints, parameters and
response keys are stable with additive-only changes; pagination tokens
are opaque strings; the error format and token restriction semantics
are stable. It lists the exempt tiers: endpoints carrying the
"unstable" marker key, debug and support endpoints (/-/threads,
/-/actions, /-/jump, the permission debug endpoints, table
autocomplete), and keys explicitly labeled unstable such as the
execute-write analysis block. Cross-referenced from the introspection
and permission-debug documentation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
2026-07-04 17:07:04 +00:00
Claude
aaaffe45b8
Return 401 for invalid or expired bearer tokens
Invalid dstok_ tokens - bad signature, malformed payload, expired, or
presented while allow_signed_tokens is off - previously degraded the
request to anonymous, so clients saw a 403 permission error or worse,
a 200 with anonymous-visible data. Token handlers can now raise
TokenInvalid for tokens they recognize but reject; Datasette responds
with 401, the canonical JSON error body and a WWW-Authenticate: Bearer
error="invalid_token" header, even when a valid cookie is also present.

Bearer tokens no registered handler recognizes are still ignored, so
authentication plugins with their own token formats keep working.
TokenInvalid is exported from the datasette package for use by plugin
token handlers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
2026-07-04 15:18:12 +00:00
Simon Willison
2f84ab77f2
Support CREATE VIEW / DROP VIEW in execute-write-sql
New create-view and drop-view actions.

Also fix a related bug in analyze_sql_tables(): SQLite's authorizer fires a spurious SQLITE_DELETE callback against the view name when a view is dropped (the same thing it does for dropped tables), which was incorrectly surfaced as a delete-row requirement on the view. Broaden the existing drop-table-delete suppression to cover dropped views too.

Closes #2819
2026-07-02 08:56:04 -07:00
Sebastian Cao
a5931594de
Document how actors are displayed (#2792)
Closes #2002
2026-06-23 14:07:56 -07:00
Simon Willison
74324cb849 Improved docs for user-facing SQL query pages
- /database-name/-/execute-write
- /-/queries
2026-05-28 15:46:27 -07:00
Simon Willison
51dab16149 Allow SQL functions in SQL write queries
Closes #2751
2026-05-28 10:22:28 -07:00
Simon Willison
cef52b1ffc Break up giant views/database.py into smaller modules 2026-05-26 16:06:14 -07:00
Simon Willison
7214cc3761 Remove obsolete label 2026-05-26 15:52:44 -07:00
Simon Willison
58e2e3a8ab Ran cog 2026-05-26 15:43:34 -07:00
Simon Willison
02a1468f1b Renamed canned queries to queries / stored queries in docs
And a few renames in code and YAML as well.
2026-05-26 15:17:51 -07:00
Simon Willison
56b14f37d5 The stored queries do not live in that DB 2026-05-26 15:16:18 -07:00
Simon Willison
4bf1c4b065 Rename canned queries to queries/stored queries in docs 2026-05-26 14:54:35 -07:00
Simon Willison
24887004cf Rename insert-query to store-query
Also queries/insert to queries/store

Refs https://github.com/simonw/datasette/pull/2741#issuecomment-4549103663
2026-05-26 14:51:59 -07:00
Simon Willison
1ac4265ffd Require permissions for untrusted stored query execution, refs #2735 2026-05-26 12:12:59 -07:00
Simon Willison
4a1a4d7807 Query is_trusted and is_private properties
Refs https://github.com/simonw/datasette/issues/2735#issuecomment-4547270516

Diff explanation: https://gist.github.com/simonw/1e4de6c4b041a51968eb273ee96dec1f
2026-05-26 11:59:49 -07:00
Simon Willison
ef43c10388 Add arbitrary write SQL execution page
Refs #2735
2026-05-25 08:30:49 -07:00
Simon Willison
4b5fac9cf7 Add query management API and create UI
Refs #2735
2026-05-24 22:52:06 -07:00
Simon Willison
be1b5b2b5c Move debug links into jump menu 2026-05-23 16:57:09 -07:00
Simon Willison
cb5cc0cc22 Fixed some broken docs/ references, refs #2671 2026-03-18 13:02:31 -07:00
Simon Willison
611b8ad463 blacken-docs 2026-03-18 12:33:09 -07:00
Simon Willison
2b06da29a1 Rename set-column-types action to et-column-type
Refs https://github.com/simonw/datasette/pull/2674#issuecomment-4085015792
2026-03-18 12:33:09 -07:00
Simon Willison
fa1d8f0fa5 set-column-types permission, refs #2671 2026-03-18 12:33:09 -07:00
Simon Willison
c96dc5ce26
register_token_handler() plugin hook for custom API token backends (#2650)
Closes #2649

* Add register_token_handler plugin hook for pluggable token backends

Adds a new register_token_handler hook that allows plugins to provide
custom token creation and verification backends. This enables plugins
like datasette-oauth to issue tokens without depending on specific
backend plugins like datasette-auth-tokens.

Key changes:
- New datasette/tokens.py with TokenHandler base class and SignedTokenHandler
  (the default signed-token implementation moved here)
- New register_token_handler hookspec in hookspecs.py
- Datasette.create_token() is now async and delegates to token handlers
- New Datasette.verify_token() method tries all handlers in sequence
- handler= parameter on create_token() to select a specific backend
- TokenHandler exported from datasette package for plugin use
- Fixed actor_from_request loop to await all coroutines (avoids warnings)

* Add documentation and hook test for register_token_handler

Fixes CI failures: the new hook needs a section in docs/plugin_hooks.rst
(checked by test_plugin_hooks_are_documented) and a test_hook_* function
in test_plugins.py (checked by test_plugin_hooks_have_tests).

* Register tokens module as separate default plugin

Instead of re-exporting hookimpls from default_permissions/__init__.py,
register datasette.default_permissions.tokens as its own DEFAULT_PLUGINS
entry. Cleaner and avoids confusing import-for-side-effect patterns.

* Replace restrict_x params with TokenRestrictions dataclass

Consolidates the three separate restrict_all, restrict_database, and
restrict_resource parameters into a single TokenRestrictions dataclass.
Cleaner API surface for both Datasette.create_token() and
TokenHandler.create_token().

Also clarifies docs re: default handler selection via pluggy ordering.

* Add builder methods to TokenRestrictions

Adds allow_all(), allow_database(), and allow_resource() methods that
return self for chaining. Callers no longer need to manipulate nested
dicts directly:

    restrictions = (TokenRestrictions()
        .allow_all("view-instance")
        .allow_database("mydb", "create-table")
        .allow_resource("mydb", "mytable", "insert-row"))

* docs: add 1.0a25 upgrade guide section for create_token() signature change

Ref: https://github.com/simonw/datasette/issues/2649#issuecomment-3962639393

* docs: note that create_token() is now async in upgrade guide

* docs: update internals, plugin_hooks, authentication for new token API

- internals.rst: new async create_token() signature with restrictions
  and handler params, add TokenRestrictions reference docs
- plugin_hooks.rst: show full create_token signature in TokenHandler
  example, note list returns and error cases
- authentication.rst: cross-reference TokenRestrictions from the
  restrictions section

* style: apply black formatting to token handler files

* docs: fix RST heading underline length in internals.rst

* tests: add restrictions round-trip and expiration tests for token handler

Covers allow_database/allow_resource builders, _r payload encoding,
and token_expires in verified actors. Coverage 76% -> 90%.

* tests: add test for signed tokens disabled

* fix: add TokenRestrictions TYPE_CHECKING import to fix ruff F821

* docs: regenerate plugins.rst with cog

* docs: reformat code blocks in plugin_hooks.rst with blacken-docs

* docs: add await .verify_token() to internals.rst

* tests: rewrite register_token_handler test to use real plugin handler

Adds a HardcodedTokenHandler to the test plugins dir that creates
tokens like dstok_hardcoded_token_1. The test now exercises creating
tokens via the default handler (which is the plugin's hardcoded one),
by explicitly naming the hardcoded handler, and by explicitly naming
the signed handler -- then verifies each token round-trips correctly.

* tests: clarify test_token_handler_via_http tests the default signed handler

* fix: use handler="signed" explicitly where signed tokens are expected

The HardcodedTokenHandler in my_plugin.py gets globally registered,
so create_token() without a handler name picks it up as the default.
Fix the create-token view, CLI, and tests to explicitly request the
signed handler where they depend on signed token behavior.

* fix: use handler="signed" in test_create_table_permissions

https://claude.ai/code/session_013cQFiDQjYRrRBH2biFfKuS
2026-02-25 16:32:45 -08:00
Simon Willison
23a640d38b
datasette serve --default-deny option (#2593)
Closes #2592
2025-11-12 16:14:21 -08:00
Simon Willison
a528555e84
Additional actor restriction should not grant access to additional actions (#2569)
Closes #2568
2025-11-01 18:38:29 -07:00
Simon Willison
e4be95b16c
Update permissions documentation for new action system (#2551) 2025-10-30 17:59:54 -07:00
Simon Willison
4fe1765dc3 Add test for RST heading underline lengths, closes #2544
Added test_rst_heading_underlines_match_title_length() to verify that RST
heading underlines match their title lengths. The test properly handles:
- Overline+underline style headings (skips validation for those)
- Empty lines before underlines (ignores them)
- Minimum 5-character underline length (avoids false positives)

Running this test identified 14 heading underline mismatches which have
been fixed across 5 documentation files:
- docs/authentication.rst (3 headings)
- docs/plugin_hooks.rst (4 headings)
- docs/internals.rst (5 headings)
- docs/deploying.rst (1 heading)
- docs/changelog.rst (1 heading)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 09:49:49 -07:00
Simon Willison
c06e05b7db New --root mechanism with datasette.root_enabled, closes #2521 2025-10-24 10:32:18 -07:00
Simon Willison
27084caa04
New allowed_resources_sql plugin hook and debug tools (#2505)
* allowed_resources_sql plugin hook and infrastructure
* New methods for checking permissions with the new system
* New /-/allowed and /-/check and /-/rules special endpoints

Still needs to be integrated more deeply into Datasette, especially for listing visible tables.

Refs: #2502

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-08 14:27:51 -07:00
Simon Willison
308c243cfd datasette.set_actor_cookie() and datasette.delete_actor_cookie(), closes #1690 2025-01-15 17:37:25 -08:00
Simon Willison
63714cb2b7 Fixed some typos spotted by Gemini Pro 1.5, closes #2318 2024-04-10 17:05:15 -07:00
Simon Willison
8bfa3a51c2 Consider every plugins opinion in datasette.permission_allowed()
Closes #2275, refs #2262
2024-02-16 13:29:39 -08:00
Simon Willison
900d15bcb8 alter table support for /db/-/create API, refs #2101 2024-02-08 13:36:17 -08:00
Simon Willison
bcf7ef963f YAML/JSON examples for allow blocks 2024-01-31 19:45:05 -08:00
Alex Garcia
35deaabcb1
Move non-metadata configuration from metadata.yaml to datasette.yaml
* Allow and permission blocks moved to datasette.yaml
* Documentation updates, initial framework for configuration reference
2023-10-12 09:16:37 -07:00
Simon Willison
31d5c4ec05 Contraction - Google and Microsoft styleguides like it
I was trying out https://github.com/errata-ai/vale
2023-09-05 19:43:01 -07:00
Simon Willison
943df09dcc Remove all remaining "$ " prefixes from docs, closes #2140
Also document sqlite-utils create-view
2023-08-11 10:44:34 -07:00
Simon Willison
c076fb65e0 Applied sphinx-inline-tabs to remaining examples, refs #1153 2023-07-08 11:00:08 -07:00
Simon Willison
e4ebef082d
Fixed link text 2023-01-21 07:37:29 -08:00
Simon Willison
5e672df168 Explicitly explain allow_sql: false 2023-01-09 08:25:07 -08:00
Simon Willison
fee658ad05 Improved wording in allow_sql docs 2023-01-05 09:22:49 -08:00
Simon Willison
c41278b46f default_allow_sql setting, closes #1409
Refs #1410
2023-01-04 16:51:26 -08:00
Simon Willison
3bd05b854a -e/--expires-after in create-token docs 2022-12-31 10:52:37 -08:00
Simon Willison
6e5ab9e7b3 Note in docs about new /-/create-token features, refs #1947 2022-12-13 21:07:03 -08:00
Simon Willison
2aa2adaa8b Docs for new create-token options, refs #1855 2022-12-12 20:56:40 -08:00
Simon Willison
14f1cc4984 Update CLI reference help, refs #1855 2022-12-12 20:21:48 -08:00
Simon Willison
8bf06a76b5
register_permissions() plugin hook (#1940)
* Docs for permissions: in metadata, refs #1636
* Refactor default_permissions.py to help with implementation of #1636
* register_permissions() plugin hook, closes #1939 - also refs #1938
* Tests for register_permissions() hook, refs #1939
* Documentation for datasette.permissions, refs #1939
* permission_allowed() falls back on Permission.default, refs #1939
* Raise StartupError on duplicate permissions
* Allow dupe permisisons if exact matches
2022-12-12 18:05:54 -08:00
Simon Willison
484bef0d3b /db/table/pk/-/update endpoint, closes #1863 2022-11-29 10:06:19 -08:00