Skip to main content

Module access_control

Module access_control 

Source
Expand description

Rule-based access control for the MCP SQLite server.

This module implements the permission system that decides which SQL operations the server may execute. Permissions are configured at startup through the --allow and --deny CLI flags, each taking an access control selector that identifies the operation — and optionally the exact resources — the rule applies to.

§Selector syntax

Every SQLite authorization action (Read, Insert, CreateTable, DropIndex, Function, etc.) has a corresponding selector type. A selector is written as:

  • Action — matches all operations of that type (every field defaults to the wildcard *).
  • Action(value) — pins the first field to a specific value; remaining fields stay as wildcards.
  • Action(value1.value2) — pins both fields.
  • Action(*.value2) — wildcard first field, pinned second field.

For example, the Read selector has two fields (table_name and column_name):

CLI flagMeaning
--allow Readallow all column reads
--deny Read(Secrets)deny reads on Secrets
--allow Read(Secrets.id)allow reads on Secrets.id
--deny Read(*.ssn)deny reads on any ssn column

§Specificity

Each selector has a specificity equal to the number of its fields that are pinned to concrete values (i.e. not *). A bare Read has specificity 0, Read(Students) has specificity 1, and Read(Students.name) has specificity 2. More specific rules always outrank less specific ones.

§Resolution algorithm

When SQLite asks “is this operation allowed?”, the AuthorizationResolver evaluates rules as follows:

  1. Collect matching rules. For each configured rule whose selector covers the requested operation (globs match anything, values must match exactly), note its specificity.

  2. Most specific wins. Rules are evaluated from the highest specificity level to the lowest. The first level that contains at least one matching rule determines the outcome.

  3. Deny breaks ties. If both allow and deny rules match at the same specificity level, the result is deny (fail-closed).

  4. Default fallback. If no rule matches at any level, the per-action default is used. The default depends on how the resolver was constructed (e.g. AuthorizationResolver::new_allow_everything ).

One sentence summary: the most specific matching rule wins; ties go to deny; no match defers to the default.

§Examples

§Read-only server with one table blocked

--allow Read --deny Read(Secrets)

All column reads are allowed except anything touching the Secrets table. Read(Secrets) has specificity 1 which beats the blanket Read at specificity 0, so the deny wins for any column in Secrets.

§Read-only with a carve-out

--allow Read --deny Read(Secrets) --allow Read(Secrets.id)

All reads are allowed. Reads on Secrets are denied — except for the id column, which is explicitly re-allowed at specificity 2 (both fields pinned), beating the specificity-1 deny.

§Conflicting rules at the same specificity

--deny Read(Students) --allow Read(*.name)

A read on Students.name matches both rules. Read(Students) has specificity 1 (table pinned, column glob) and Read(*.name) also has specificity 1 (table glob, column pinned). Because both match at the same level, deny wins. To allow Students.name, add a more specific rule: --allow Read(Students.name) (specificity 2).

§Deny everything, allow specific functions

--deny Function --allow Function(count) --allow Function(sum)

All SQL function calls are denied except count and sum, which win at specificity 1 over the blanket deny at specificity 0.

§Lock down DDL while permitting reads and inserts

--allow Read --allow Insert --allow Select --allow Transaction

With a deny-everything default, only the explicitly allowed actions proceed. All DDL (CreateTable, DropIndex, etc.) remains denied because no allow rule exists for those actions.

§Code generation

The define_access_control_selector_types! macro generates the selector structs, the AccessControlSelector enum, the AccessControlSelectorSet, and the AuthorizationResolver from a set of struct declarations. Each struct’s field types are wrapped in ValueOrGlob so that every field can independently be a concrete value or a wildcard. The macro also generates Display / FromStr round-tripping, builder methods, and the specificity-aware resolution logic described above.

Structs§

AccessControlSelectorSet
Holds all configured access control rules, grouped by selector type and indexed by specificity.
AlterTable
Selector for ALTER TABLE statements, scoped to a database and table.
Analyze
Selector for ANALYZE statements, scoped to a table.
Attach
Selector for ATTACH DATABASE statements, scoped to a filename.
AuthorizationResolver
Resolves incoming SQLite authorization requests against a set of configured allow/deny rules and per-action default permissions.
CreateIndex
Selector for CREATE INDEX statements, scoped to a table and index name.
CreateTable
Selector for CREATE TABLE statements.
CreateTempIndex
Selector for CREATE TEMP INDEX statements, scoped to a table and index name.
CreateTempTable
Selector for CREATE TEMP TABLE statements.
CreateTempTrigger
Selector for CREATE TEMP TRIGGER statements, scoped to a table and trigger name.
CreateTempView
Selector for CREATE TEMP VIEW statements.
CreateTrigger
Selector for CREATE TRIGGER statements, scoped to a table and trigger name.
CreateView
Selector for CREATE VIEW statements.
CreateVtable
Selector for CREATE VIRTUAL TABLE statements, scoped to a table and module name.
Delete
Selector for DELETE statements, scoped to a table.
Detach
Selector for DETACH DATABASE statements, scoped to a database name.
DropIndex
Selector for DROP INDEX statements, scoped to a table and index name.
DropTable
Selector for DROP TABLE statements.
DropTempIndex
Selector for DROP TEMP INDEX statements, scoped to a table and index name.
DropTempTable
Selector for DROP TEMP TABLE statements.
DropTempTrigger
Selector for DROP TEMP TRIGGER statements, scoped to a table and trigger name.
DropTempView
Selector for DROP TEMP VIEW statements.
DropTrigger
Selector for DROP TRIGGER statements, scoped to a table and trigger name.
DropView
Selector for DROP VIEW statements.
DropVtable
Selector for DROP VIRTUAL TABLE statements, scoped to a table and module name.
Function
Selector for SQL function invocations within a query.
Glob
A wildcard marker that matches any value in a selector field.
Insert
Selector for INSERT statements, scoped to a table.
Permission
Pairs a selector with a permission disposition (allow or deny).
Pragma
Selector for PRAGMA statements, scoped to a pragma name
Read
Selector for column-level read operations, scoped to a table and column.
Recursive
Selector for recursive query authorization checks.
Reindex
Selector for REINDEX statements, scoped to an index name.
Savepoint
Selector for SAVEPOINT, RELEASE, and ROLLBACK TO operations on named savepoints.
Select
Selector for bare SELECT operations (the statement-level authorization check, not column-level reads).
Transaction
Selector for transaction control operations (BEGIN, COMMIT, ROLLBACK).
Update
Selector for UPDATE statements, scoped to a table and column.

Enums§

AccessControlSelector
Umbrella enum unifying all access control selector types into a single type for use with the CLI argument parser.
AccessControlSelectorParseError
Enumerates the ways parsing an access control selector string can fail.
Authorization
The outcome of a policy check against the configured rule set.
Preset
Predefined permission presets for common access control configurations.
TransactionOperation
The type of transaction or savepoint operation being authorized.
ValueOrGlob
Either a concrete value of type T or a wildcard Glob.