Admin-machine surface, impersonation, and auto-admin for Intent API products.
Project description
Intent API Admin
Console-issued admin tokens, impersonation, and zero-boilerplate admin surfaces for any Intent API product.
intent-api-admin plugs into intent-api to add a dedicated admin-machine surface, Ed25519/JWKS-verified admin and impersonation tokens, an automatic CRUD admin generator from your SQLAlchemy models, role-aware role gates, audit correlation, and a schema document the console can render directly.
Install
pip install intent-api-admin
Requires intent-api>=0.5.0 and Python 3.10+.
Three-step integration
from intent_api import IntentRouter
from intent_api_admin import (
configure_admin_auth, auto_admin,
admin_machine_auth, impersonation_aware_auth,
)
configure_admin_auth(
issuer="https://console.example.com",
audience="myapp",
impersonation_user_query=lambda db, uid: db.query(User).get(uid),
base=Base,
)
router = IntentRouter()
router.register("User", UserService())
auto_admin(router, expose=["User", "Team"])
app.include_router(router.build(get_user=impersonation_aware_auth(get_clerk_user), get_db=get_db))
app.include_router(router.build_admin_machine(get_user=admin_machine_auth(), get_db=get_db))
That is the entire integration. Console operators now get full read/write CRUD on every model in expose=[...] plus impersonation on top of your existing user auth, and your handlers are unchanged.
Roles
Three roles, ordered by rank:
| Role | Rank | Default for |
|---|---|---|
owner |
3 | delete on auto-admin services |
admin |
2 | update, default for @custom_action(admin_only=True) |
support |
1 | list, read |
A higher-ranked role satisfies any lower-ranked requirement. So an owner token can perform any action that requires support, admin, or owner.
Heuristic defaults
auto_admin() reads each SQLAlchemy model and picks sensible defaults you almost never need to override.
list_fields— primary key +name/email/title/slug/status/created_atif present, then non-text columns up to 6 total.search_fields— string columns withindex=Trueorunique=Trueandlength<=255.default_sort—created_at descif present; otherwise<primary_key> desc.- Auto-redaction patterns — any column whose name starts with
password,secret,api_key,token, or_, or ends with_hash/_digest. Redacted fields are stripped from responses and refused on update.
Override patterns
auto_admin(
router,
expose=["User", "Team", "Order"],
redact_fields={"User": ["last_login_ip"]}, # add to auto-redaction
deny_edit_fields={"User": ["email"]}, # read-only in admin
deny_delete=["Order"], # disallow delete entirely
overrides={ # surgical schema override
"User": {"default_sort": "email asc",
"list_fields": ["id", "email", "name", "plan", "is_active"]},
},
)
Custom admin actions
Use the augmented @custom_action from intent_api_admin for admin-only commands. They are dispatched on the admin-machine surface only — invisible to standard, MCP, machine, and the legacy admin route.
from intent_api_admin import custom_action
class UserService(IntentService):
@custom_action(admin_only=True, min_role="admin")
async def ban(self, *, db, user, context, id, payload):
...
@custom_action(admin_only=True, min_role="support", read_only=True)
async def view_audit(self, *, db, user, context, id, payload):
...
read_only=True makes the command callable under read-only impersonation sessions. Without it, the precondition layer raises IMPERSONATION_WRITE_DENIED (HTTP 403).
Common errors and fixes
| Code | When | Fix |
|---|---|---|
ADMIN_AUTH_NOT_CONFIGURED |
auto_admin() called before configure_admin_auth() |
Call configure_admin_auth(...) first. |
CONFIGURATION_ORDER_ERROR |
configure_admin_auth() called again after auto_admin() ran |
Reset only in tests; in prod call exactly once at startup. |
MODEL_NOT_FOUND |
expose=["X"] but X isn't on Base.registry |
Make sure the model is imported before auto_admin(). |
WRONG_SURFACE |
Admin token on /api/intent or impersonation token on /api/admin-machine-intent |
Use the correct surface for the token mode. |
IMPERSONATION_WRITE_DENIED |
A write action ran under a read-only impersonation token | Issue a token with allow_writes=true, or mark the action read_only=True. |
INSUFFICIENT_ROLE |
Token role rank is below the action's min_role |
Issue a token with the required role. |
FIELD_REDACTED |
Update payload references a redacted field | Drop the field from payload, or remove from redact_fields. |
FIELD_READ_ONLY |
Update payload references a deny_edit_fields field |
Drop the field, or remove the deny entry. |
DELETE_DENIED |
Delete on a deny_delete model |
Remove the model from deny_delete=[...]. |
UNSUPPORTED_FILTER_OP |
List filter uses an op the auto-admin filter parser doesn't support | Use one of eq, ne, lt, lte, gt, gte, contains, in, is_null. |
See TOKEN_CONTRACT.md for the full token spec.
Reference test suite
tests/wbs_reference/ is an exhaustive contract suite that mirrors the WBS success criteria S1–S52. Copy it into your repo to validate every adoption.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file intent_api_admin-0.1.0.tar.gz.
File metadata
- Download URL: intent_api_admin-0.1.0.tar.gz
- Upload date:
- Size: 50.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc68b5296be3feeea8c8eb1983aa9cf9566d571ab7e16103ba211cc2d5a76a63
|
|
| MD5 |
f0ddad89d9a92928fe5dcb63c6af0cdf
|
|
| BLAKE2b-256 |
387882234087c0cdbe4cac3cf96d52944831245d87b269f32ceb8f8bd6c6e120
|
File details
Details for the file intent_api_admin-0.1.0-py3-none-any.whl.
File metadata
- Download URL: intent_api_admin-0.1.0-py3-none-any.whl
- Upload date:
- Size: 35.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1ce9d6643c552076adac2b95ef84ba3a55aabbd2356f637027bc383df97f6e7
|
|
| MD5 |
916624719b6789ad0d64d6ce47508fcd
|
|
| BLAKE2b-256 |
e698b121642c59966d3d7d7ba1771e9fd83c7a9ec2ededa493e251e14e549160
|