Repository navigation
Conversation
… listings Arc's three database listing endpoints carried no authentication at all. They now require read permission and, where the server restricts reads per database, a grant covering the database being listed. handle_response_error mapped both 401 and 403 onto ArcAuthenticationError, so a caller could not tell "re-authenticate" from "this token lacks a permission" — and 403 is not one condition either. Arc answers it for a token with no read permission, for a token whose grants do not cover the database asked for, for a licence-gated feature, and for its own permission data being unreadable, distinguishing them only by message. ArcAuthenticationError now means 401 only. Added: - ArcPermissionError: the token does not carry the permission the endpoint requires. - ArcScopedAccessError: Arc's per-database denial. The token may read, but not what was asked for. Carries the refused database on .database — empty or "*" when the call asked for every database, since Arc refuses databases.list() for a tenant-scoped token rather than returning a filtered list, matching SHOW DATABASES. A normal state, not a fault to retry. - ArcPermissionDataUnavailableError: Arc could not load the token's grants and failed closed. A server-side fault that says nothing about the token, so it is checked before the scoped shape and never reported as one. All subclass ArcPermissionError, which subclasses ArcAuthenticationError, so existing except blocks that caught 403 as an authentication failure keep working. Matching is by stable message fragment and covers both the read middleware's wording and the handler gates', so a change to the permission word cannot reclassify one refusal as another; an unrecognised 403 falls back to ArcPermissionError. Docstrings on list/get/list_measurements, sync and async, document which exception each refusal raises.
5 tasks done
This was referenced Oct 27, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Arc's three database listing endpoints (
GET /api/v1/databases,/:name,/:name/measurements) previously carried no authentication at all. They now require read permission and, where the server restricts reads per database, a grant covering the database being listed.handle_response_errormapped both 401 and 403 ontoArcAuthenticationError, so a caller could not tell "re-authenticate" from "this token lacks a permission". And 403 is not one condition either — Arc answers it for four different things, told apart only by message.ArcAuthenticationError— token missing, invalid or expiredno permission for read on database 'x'/access denied: no read permission for database 'x'ArcScopedAccessError— may read, but not that database;.databasecarries ittoken does not have 'read' permission/Permission denied: read requiredArcPermissionError— no read permission at allpermission data unavailableArcPermissionDataUnavailableError— Arc could not load the grants; a server-side faultArcLicenseError(unchanged)ArcNotFoundError— unchanged, so "you may not read it" and "it is not there" stay apartArcAuthenticationErrornow means 401 only. The three new classes all subclassArcPermissionError, which subclassesArcAuthenticationError, so existingexceptblocks that caught 403 as an authentication failure keep working.databases.list()and a scoped tokenArc refuses the list-everything route for a token restricted to particular databases rather than returning a filtered list, the same way
SHOW DATABASESdoes. That is a normal state for a tenant-scoped token, not a fault to retry:.databasecarries the refused database, and is empty or"*"when the call asked for every database — so test it againstNone, not truthiness, to tell "not scoped" from "scoped, no name".Nothing changes for an admin token, for a read token on a server that does not restrict reads per database, or for a server with authentication disabled.
Notes
ArcPermissionError, which is safe to say about any refusal.permission data unavailableis checked before the scoped shape: a broken permission store must never send a caller after a database that was never the problem.Companion to the Arc server change on
fix/rbac-measurement-where-and-databases-auth; see that branch's release notes under "RBAC read and write restrictions were unreachable, and the database listings had no authorization".Test plan
uv run ruff check .+uv run ruff format --check .cleanuv run mypy src/arc_client --ignore-missing-imports— no issues (the CI invocation)uv run pytest tests/unit— 184 passed, 9 skippedtests/unit/http/test_databases_permissions.py(26 tests,pytest-httpxas the rest of the suite uses): the exception hierarchy;list()/get()/list_measurements()against every body; a parametrised matrix asserting the exact type per 403 message (not just "a subclass of something"); 404 staying separate; the licence 403 keeping its own exception; and the async twinhttp/base.py, run, restore): 9 failurestest_error_status_mappingcase(403, ArcAuthenticationError)still passes via the subclass chain[0.2.0], and theRaises:sections of all six database methods