Skip to content

http-auth done - #36

Open
NEMEZIZ1234 wants to merge 1 commit into
mienetic:mainfrom
NEMEZIZ1234:feat/10-http-auth
Open

NEMEZIZ1234 wants to merge 1 commit into
mienetic:mainfrom
NEMEZIZ1234:feat/10-http-auth

Conversation

@NEMEZIZ1234

Copy link
Copy Markdown

Summary

Adds HTTP API-key auth with per-key scope prefixes (multi-tenant): requests are rejected with 401 when auth is configured and a valid key isn't provided, and each key is restricted to its configured scope prefix. Enforced on both the MCP streamable-HTTP transport and the REST API.

Related issue

Closes #10

Changes

  • src/mnema/auth.py (new) β€” AuthContext/Authenticator, ApiKeyAuthMiddleware (ASGI, for the MCP transport), parse_api_keys, and request_auth/set_auth/current_auth context-var helpers.
  • config.py β€” new api_keys field (key1=user:alice:*,key2 β€” bare key = full access; empty = auth disabled), parsed via NoDecode + mode="before" validator (pydantic-settings β‰₯ 2.2).
  • api/app.py β€” get_auth FastAPI dependency (401 when missing/invalid), ForbiddenError β†’ 403 handler, /memories list clamped + denied for out-of-prefix scopes.
  • server.py β€” _run_http wraps streamable_http_app() behind ApiKeyAuthMiddleware; FastMCP(host=...) so the DNS-rebinding allowlist matches remote hosts.
  • service.py β€” _enforce_scope / _tenant_scope / _outside_prefix: writes β†’ 403, reads clamp to the key's prefix, by-id get/update/forget β†’ 404 on out-of-prefix ids, list_scopes/stats filtered, decay/reembed/summarize enforced.
  • errors.py β€” added ForbiddenError.
  • pyproject.toml β€” pydantic-settings>=2.2; version bumped to 0.5.0.
  • Tests β€” new test_auth.py, test_http_auth.py (real MCP streamable client); extended test_api.py, test_config.py.
  • Docs β€” README.md, docs/deployment.md, packages/mnema-extension/README.md (auth section); CHANGELOG [Unreleased] entry.

Checklist

  • ruff check . is clean
  • pytest passes (with the relevant [extra] installed if you touched a backend)
  • New public functions / classes have docstrings
  • Docs updated (README.md, SKILL.md, docs/) if user-facing behavior changed
  • If this adds a backend or embedding provider: registered in the factory (__init__.py::make_*), added an [extra] in pyproject.toml, and added a test class

Notes for reviewer

  • Auth is mandatory when configured (MNEMA_API_KEYS set) β€” 401 otherwise β€” and fully disabled when unset (backwards compatible).
  • Env format is key=scope:prefix,key2 (comma-separated); pydantic-settings JSON-decodes complex env values before validators, so the field uses Annotated[..., NoDecode] (requires β‰₯ 2.2).
  • Tenant semantics: explicit out-of-prefix writes β†’ 403; reads on by-id ops return 404 (as MemoryNotFoundError) so tenants can't probe each other; list/search read paths clamp to the key's prefix when no scope is given.
  • REST uses a FastAPI Depends; the context var needs no reset there (per-request ASGI task). The MCP transport needs a middleware (reset per stream) per the issue spec.
  • FastMCP(host=cfg.http_host) was required so the loopback DNS-rebinding allowlist matches the clients served; a non-loopback host disables rebinding protection, which auth now covers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Auth + multi-tenant enforcement for HTTP transport

1 participant