Files
lda-wf/docs/historical/superpowers/plans/2026-06-06-auth-store-boundary-slice-1.md
T

24 KiB

Auth Store Boundary Slice 1 Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Add a neutral auth record/store boundary and make current MCP auth loading prefer source auth_ref while preserving legacy connection-id behavior.

Architecture: wf_api owns neutral auth ids, records, and the read-only auth-store protocol. wf_mcp keeps its current AuthRecord compatibility type, but adds adapter helpers that convert neutral records into MCP runtime records and centralize MCP payload interpretation. No diagnostics, admin mutation, OAuth, or secret-manager behavior in this slice.

Tech Stack: Python 3.14, dataclasses, protocols, pytest, ruff, basedpyright.


Scope

Implement only:

  • neutral auth model/protocol in wf_api
  • MCP file-store adapter bridge
  • MCP runtime auth resolution by metadata["auth_ref"] with legacy fallback
  • central MCP auth payload interpretation helper

Do not implement:

  • auth admin CLI/RPC/MCP tools
  • auth diagnostics in deployment validation
  • OAuth/browser flows
  • encrypted file format
  • source-provider packages beyond current wf_mcp

Files

  • Create: src/wf_api/auth.py
    • neutral AUTH_ID_PATTERN
    • validate_auth_id
    • frozen AuthRecord
    • read-only AuthStore protocol
  • Modify: src/wf_api/__init__.py
    • export neutral auth symbols
  • Create: tests/wf_api/test_auth.py
    • neutral auth model/protocol tests
  • Create: src/wf_mcp/auth.py
    • adapter helpers between neutral auth and wf_mcp.models.AuthRecord
    • centralized MCP header/env extraction
  • Modify: src/wf_mcp/storage/store.py
    • add neutral load_auth_record(auth_ref) / save_auth_record(record) methods
    • keep old save_auth(AuthRecord) / load_auth(connection_id) methods
  • Modify: src/wf_mcp/broker/service/upstream_transport.py
    • add load_connection_auth(connection) helper
    • update all load_auth(connection.id) call sites to use the helper
    • keep load_auth(connection_id) facade for compatibility
  • Modify: src/wf_mcp/broker/service/source_catalog.py
    • change AuthLoader from Callable[[str], AuthRecord | None] to Callable[[ConnectionConfig], AuthRecord | None]
    • update hydrated wrapper calls to pass the connection object
  • Modify: src/wf_mcp/broker/service/core.py
    • pass self.upstream.load_connection_auth to SourceCatalogService
  • Modify: src/wf_mcp/sdk/adapter.py
    • replace local _auth_headers / env payload reads with wf_mcp.auth helpers
  • Modify: src/wf_mcp/runtime/factory.py
    • replace local _auth_headers / env payload reads with wf_mcp.auth helpers
  • Test: tests/wf_mcp/test_auth.py
    • adapter bridge tests
  • Test: tests/wf_mcp/service/test_upstream_transport.py
    • auth_ref lookup / fallback tests
  • Test: existing focused suites listed below

Task 1: Neutral auth model and store protocol

Files:

  • Create: src/wf_api/auth.py

  • Modify: src/wf_api/__init__.py

  • Create: tests/wf_api/test_auth.py

  • Step 1: Write neutral auth tests

Create tests/wf_api/test_auth.py:

from __future__ import annotations

from collections.abc import Mapping
from typing import assert_type

import pytest

from wf_api.auth import AuthRecord, AuthStore, validate_auth_id


def test_validate_auth_id_accepts_safe_dotted_ids() -> None:
    assert validate_auth_id("github.work") == "github.work"
    assert validate_auth_id("api_ci-1") == "api_ci-1"


@pytest.mark.parametrize("auth_id", ["", ".hidden", "../secret", "bad/id"])
def test_validate_auth_id_rejects_unsafe_ids(auth_id: str) -> None:
    with pytest.raises(ValueError, match="auth id must start"):
        validate_auth_id(auth_id)


def test_auth_record_is_immutable_and_mapping_typed() -> None:
    record = AuthRecord(
        id="github.work",
        scheme="bearer",
        payload={"token": "secret"},
        metadata={"owner": "test"},
    )

    assert record.id == "github.work"
    assert record.scheme == "bearer"
    assert record.payload["token"] == "secret"
    assert_type(record.payload, Mapping[str, object])

    with pytest.raises(AttributeError):
        record.scheme = "headers"  # type: ignore[misc]


class MemoryAuthStore:
    def __init__(self, records: dict[str, AuthRecord]) -> None:
        self.records = records

    def load_auth(self, auth_ref: str) -> AuthRecord | None:
        return self.records.get(auth_ref)


def test_auth_store_protocol_is_read_only_lookup() -> None:
    record = AuthRecord(id="github.work", scheme="opaque", payload={"x": 1})
    store: AuthStore = MemoryAuthStore({"github.work": record})

    assert store.load_auth("github.work") is record
    assert store.load_auth("missing") is None
  • Step 2: Run test to verify failure

Run:

uv run pytest tests/wf_api/test_auth.py -q

Expected: fails because wf_api.auth does not exist.

  • Step 3: Implement neutral auth module

Create src/wf_api/auth.py:

from __future__ import annotations

import re
from collections.abc import Mapping
from dataclasses import dataclass, field
from typing import Protocol

AUTH_ID_PATTERN = r"^[A-Za-z0-9_][A-Za-z0-9_.-]*$"


def validate_auth_id(value: str) -> str:
    """Validate auth refs that are safe as store keys and path segments.

    Auth refs deliberately carry no provider semantics. Source providers decide
    how a resolved auth record is interpreted.
    """

    if not re.fullmatch(AUTH_ID_PATTERN, value):
        raise ValueError(
            "auth id must start with alphanumeric or underscore and contain "
            "only [A-Za-z0-9_.-]"
        )
    return value


@dataclass(frozen=True, slots=True)
class AuthRecord:
    """Neutral credential record resolved by auth ref.

    `scheme + payload` is a compatibility bridge, not the long-term taxonomy.
    Keep payload interpretation inside provider adapters so a future
    discriminated union can replace this without touching workflow/config code.
    """

    id: str
    scheme: str
    payload: Mapping[str, object]
    metadata: Mapping[str, object] = field(default_factory=dict)

    def __post_init__(self) -> None:
        validate_auth_id(self.id)
        if not self.scheme:
            raise ValueError("auth scheme must be non-empty")


class AuthStore(Protocol):
    """Read-only runtime credential lookup by auth ref."""

    def load_auth(self, auth_ref: str) -> AuthRecord | None: ...


__all__ = [
    "AUTH_ID_PATTERN",
    "AuthRecord",
    "AuthStore",
    "validate_auth_id",
]
  • Step 4: Export from wf_api

Modify src/wf_api/__init__.py:

from .auth import AUTH_ID_PATTERN, AuthRecord, AuthStore, validate_auth_id

Add these entries to __all__:

"AUTH_ID_PATTERN",
"AuthRecord",
"AuthStore",
"validate_auth_id",
  • Step 5: Run focused tests

Run:

uv run pytest tests/wf_api/test_auth.py tests/wf_api/test_import_direction.py -q
uv run ruff check src/wf_api/auth.py tests/wf_api/test_auth.py
uv run basedpyright --level error src/wf_api tests/wf_api/test_auth.py

Expected: all pass.

Task 2: MCP auth adapter helpers

Files:

  • Create: src/wf_mcp/auth.py

  • Create: tests/wf_mcp/test_auth.py

  • Step 1: Write MCP adapter tests

Create tests/wf_mcp/test_auth.py:

from __future__ import annotations

from wf_api.auth import AuthRecord as NeutralAuthRecord
from wf_mcp.auth import (
    mcp_auth_env,
    mcp_auth_headers,
    mcp_auth_from_neutral,
    neutral_auth_from_mcp,
)
from wf_mcp.models import AuthRecord as McpAuthRecord


def test_mcp_auth_from_neutral_preserves_scheme_and_payload() -> None:
    neutral = NeutralAuthRecord(
        id="github.work",
        scheme="bearer",
        payload={"token": "secret"},
        metadata={"owner": "test"},
    )

    mcp = mcp_auth_from_neutral(neutral)

    assert mcp == McpAuthRecord(
        connection_id="github.work",
        scheme="bearer",
        payload={"token": "secret"},
    )


def test_neutral_auth_from_mcp_preserves_payload() -> None:
    mcp = McpAuthRecord(
        connection_id="github.work",
        scheme="headers",
        payload={"headers": {"X-Test": "yes"}},
    )

    neutral = neutral_auth_from_mcp(mcp)

    assert neutral.id == "github.work"
    assert neutral.scheme == "headers"
    assert neutral.payload == {"headers": {"X-Test": "yes"}}


def test_mcp_auth_headers_extracts_explicit_headers_and_bearer_token() -> None:
    auth = McpAuthRecord(
        connection_id="api.work",
        scheme="bearer",
        payload={"headers": {"X-Test": "yes"}, "token": "secret"},
    )

    assert mcp_auth_headers(auth) == {
        "X-Test": "yes",
        "Authorization": "Bearer secret",
    }


def test_mcp_auth_headers_does_not_override_authorization_header() -> None:
    auth = McpAuthRecord(
        connection_id="api.work",
        scheme="bearer",
        payload={
            "headers": {"Authorization": "Basic already"},
            "token": "secret",
        },
    )

    assert mcp_auth_headers(auth) == {"Authorization": "Basic already"}


def test_mcp_auth_env_returns_string_map_only() -> None:
    auth = McpAuthRecord(
        connection_id="mcp.local",
        scheme="env",
        payload={"env": {"TOKEN": "secret", "BAD": 123}},
    )

    assert mcp_auth_env(auth) == {"TOKEN": "secret"}
  • Step 2: Run test to verify failure

Run:

uv run pytest tests/wf_mcp/test_auth.py -q

Expected: fails because wf_mcp.auth does not exist.

  • Step 3: Implement MCP adapter module

Create src/wf_mcp/auth.py:

from __future__ import annotations

from wf_api.auth import AuthRecord as NeutralAuthRecord

from .models import AuthRecord as McpAuthRecord


def mcp_auth_from_neutral(record: NeutralAuthRecord) -> McpAuthRecord:
    """Adapt neutral auth to the current MCP compatibility record."""

    return McpAuthRecord(
        connection_id=record.id,
        scheme=record.scheme,
        payload=dict(record.payload),
    )


def neutral_auth_from_mcp(record: McpAuthRecord) -> NeutralAuthRecord:
    """Adapt legacy MCP auth into the neutral record shape."""

    return NeutralAuthRecord(
        id=record.connection_id,
        scheme=record.scheme,
        payload=dict(record.payload),
    )


def mcp_auth_headers(auth: McpAuthRecord | None) -> dict[str, str]:
    """Return HTTP headers understood by MCP HTTP transports.

    This is intentionally MCP-specific. Neutral code must not inspect payload
    keys such as `headers` or `token`.
    """

    if auth is None:
        return {}
    raw_headers = auth.payload.get("headers", {})
    headers = {
        str(key): str(value)
        for key, value in raw_headers.items()
        if isinstance(key, str) and isinstance(value, str)
    } if isinstance(raw_headers, dict) else {}
    token = auth.payload.get("token")
    if isinstance(token, str) and "Authorization" not in headers:
        headers["Authorization"] = f"Bearer {token}"
    return headers


def mcp_auth_env(auth: McpAuthRecord | None) -> dict[str, str]:
    """Return environment variables understood by MCP stdio transports."""

    if auth is None:
        return {}
    raw_env = auth.payload.get("env", {})
    if not isinstance(raw_env, dict):
        return {}
    return {
        str(key): str(value)
        for key, value in raw_env.items()
        if isinstance(key, str) and isinstance(value, str)
    }


__all__ = [
    "mcp_auth_env",
    "mcp_auth_from_neutral",
    "mcp_auth_headers",
    "neutral_auth_from_mcp",
]
  • Step 4: Run focused tests

Run:

uv run pytest tests/wf_mcp/test_auth.py -q
uv run ruff check src/wf_mcp/auth.py tests/wf_mcp/test_auth.py
uv run basedpyright --level error src/wf_mcp/auth.py tests/wf_mcp/test_auth.py

Expected: all pass.

Task 3: Store adapter bridge

Files:

  • Modify: src/wf_mcp/storage/store.py

  • Modify: tests/wf_mcp/test_auth.py

  • Step 1: Add store bridge tests

Append to tests/wf_mcp/test_auth.py:

from pathlib import Path

from wf_mcp.storage import FileStore


def test_file_store_saves_and_loads_neutral_auth_record(tmp_path: Path) -> None:
    store = FileStore(tmp_path)
    record = NeutralAuthRecord(
        id="github.work",
        scheme="bearer",
        payload={"token": "secret"},
        metadata={"owner": "test"},
    )

    store.save_auth_record(record)

    loaded = store.load_auth_record("github.work")
    assert loaded == record


def test_file_store_legacy_auth_methods_still_work(tmp_path: Path) -> None:
    store = FileStore(tmp_path)
    legacy = McpAuthRecord(
        connection_id="github.work",
        scheme="bearer",
        payload={"token": "secret"},
    )

    store.save_auth(legacy)

    assert store.load_auth("github.work") == legacy
    assert store.load_auth_record("github.work") == NeutralAuthRecord(
        id="github.work",
        scheme="bearer",
        payload={"token": "secret"},
    )
  • Step 2: Run tests to verify failure

Run:

uv run pytest tests/wf_mcp/test_auth.py::test_file_store_saves_and_loads_neutral_auth_record tests/wf_mcp/test_auth.py::test_file_store_legacy_auth_methods_still_work -q

Expected: fails because FileStore.save_auth_record / load_auth_record do not exist.

  • Step 3: Extend store interface and file store

Modify src/wf_mcp/storage/store.py:

Add imports:

from wf_api.auth import AuthRecord as NeutralAuthRecord

from ..auth import mcp_auth_from_neutral, neutral_auth_from_mcp

Add to class Store:

    def save_auth_record(self, record: NeutralAuthRecord) -> None:
        raise NotImplementedError

    def load_auth_record(self, auth_ref: str) -> NeutralAuthRecord | None:
        raise NotImplementedError

Add to class FileStore:

    def save_auth_record(self, record: NeutralAuthRecord) -> None:
        """Save neutral auth through the legacy MCP file shape."""

        self.save_auth(mcp_auth_from_neutral(record))

    def load_auth_record(self, auth_ref: str) -> NeutralAuthRecord | None:
        """Load neutral auth from the legacy MCP file shape."""

        record = self.load_auth(auth_ref)
        if record is None:
            return None
        return neutral_auth_from_mcp(record)

Do not change the existing on-disk JSON shape in this task.

  • Step 4: Run focused tests

Run:

uv run pytest tests/wf_mcp/test_auth.py -q
uv run ruff check src/wf_mcp/storage/store.py tests/wf_mcp/test_auth.py
uv run basedpyright --level error src/wf_mcp/storage/store.py tests/wf_mcp/test_auth.py

Expected: all pass.

Task 4: Runtime auth resolution by auth_ref with fallback

Files:

  • Modify: src/wf_mcp/broker/service/upstream_transport.py

  • Modify: src/wf_mcp/broker/service/source_catalog.py

  • Modify: src/wf_mcp/broker/service/core.py

  • Modify: tests/wf_mcp/service/test_upstream_transport.py

  • Step 1: Add upstream resolution tests

Open tests/wf_mcp/service/test_upstream_transport.py. Add imports if missing:

from pathlib import Path

from wf_mcp.models import AuthRecord, ConnectionConfig
from wf_mcp.storage import FileStore

Add helper if the file does not already have one:

def _transport(root: Path) -> UpstreamTransportService:
    events: list[object] = []
    return UpstreamTransportService(
        store=FileStore(root),
        event_sink=events.append,
    )

Add tests:

def test_upstream_load_connection_auth_prefers_auth_ref(tmp_path: Path) -> None:
    service = _transport(tmp_path)
    service.save_auth(
        AuthRecord(
            connection_id="github.creds",
            scheme="bearer",
            payload={"token": "secret"},
        )
    )
    service.save_auth(
        AuthRecord(
            connection_id="github.work",
            scheme="bearer",
            payload={"token": "wrong"},
        )
    )
    connection = ConnectionConfig(
        id="github.work",
        server="github",
        account="work",
        metadata={"auth_ref": "github.creds"},
    )

    assert service.load_connection_auth(connection) == AuthRecord(
        connection_id="github.creds",
        scheme="bearer",
        payload={"token": "secret"},
    )


def test_upstream_load_connection_auth_falls_back_to_connection_id(
    tmp_path: Path,
) -> None:
    service = _transport(tmp_path)
    service.save_auth(
        AuthRecord(
            connection_id="github.work",
            scheme="bearer",
            payload={"token": "legacy"},
        )
    )
    connection = ConnectionConfig(
        id="github.work",
        server="github",
        account="work",
    )

    assert service.load_connection_auth(connection) == AuthRecord(
        connection_id="github.work",
        scheme="bearer",
        payload={"token": "legacy"},
    )


def test_upstream_load_connection_auth_ignores_non_string_auth_ref(
    tmp_path: Path,
) -> None:
    service = _transport(tmp_path)
    service.save_auth(
        AuthRecord(
            connection_id="github.work",
            scheme="bearer",
            payload={"token": "legacy"},
        )
    )
    connection = ConnectionConfig(
        id="github.work",
        server="github",
        account="work",
        metadata={"auth_ref": 123},
    )

    assert service.load_connection_auth(connection) == AuthRecord(
        connection_id="github.work",
        scheme="bearer",
        payload={"token": "legacy"},
    )

If the file already has a helper for UpstreamTransportService, use it instead of adding _transport.

  • Step 2: Run tests to verify failure

Run:

uv run pytest tests/wf_mcp/service/test_upstream_transport.py -q

Expected: fails because load_connection_auth does not exist.

  • Step 3: Implement load_connection_auth

Modify src/wf_mcp/broker/service/upstream_transport.py.

Add method to UpstreamTransportService after load_auth:

    def load_connection_auth(self, connection: ConnectionConfig) -> AuthRecord | None:
        """Resolve auth for a connection, preferring explicit source auth_ref.

        Legacy MCP auth records are keyed by connection id. New source registry
        and neutral config entries carry `auth_ref`; keep both paths until the
        old compatibility surface has no callers.
        """

        auth_ref = connection.metadata.get("auth_ref")
        if isinstance(auth_ref, str):
            return self.load_auth(auth_ref)
        return self.load_auth(connection.id)
  • Step 4: Replace direct connection-id auth lookups in upstream transport

In src/wf_mcp/broker/service/upstream_transport.py, replace these patterns:

auth = self.load_auth(connection.id)

with:

auth = self.load_connection_auth(connection)

Also replace the live-check lookup:

auth = self.load_auth(source_id)

with:

auth = self.load_connection_auth(connection)

Keep load_auth(connection_id) unchanged as a compatibility facade.

  • Step 5: Update source catalog auth callback

Modify src/wf_mcp/broker/service/source_catalog.py.

Change:

AuthLoader = Callable[[str], AuthRecord | None]

to:

AuthLoader = Callable[[ConnectionConfig], AuthRecord | None]

Inside spec_from_snapshot_entry.invoke_tool, change:

connection = self.connection_lookup(entry.connection_id)
auth = self.load_auth(entry.connection_id)

to:

connection = self.connection_lookup(entry.connection_id)
auth = self.load_auth(connection)
  • Step 6: Wire source catalog to the new resolver

Modify src/wf_mcp/broker/service/core.py.

In SourceCatalogService(...) construction, change:

load_auth=self.upstream.load_auth,

to:

load_auth=self.upstream.load_connection_auth,
  • Step 7: Run focused tests

Run:

uv run pytest tests/wf_mcp/service/test_upstream_transport.py tests/wf_mcp/service/test_catalog.py tests/wf_mcp/service/test_workflow_runtime.py -q
uv run ruff check src/wf_mcp/broker/service/upstream_transport.py src/wf_mcp/broker/service/source_catalog.py src/wf_mcp/broker/service/core.py tests/wf_mcp/service/test_upstream_transport.py
uv run basedpyright --level error src/wf_mcp/broker/service tests/wf_mcp/service/test_upstream_transport.py

Expected: all pass.

Task 5: Centralize MCP payload interpretation

Files:

  • Modify: src/wf_mcp/sdk/adapter.py

  • Modify: src/wf_mcp/runtime/factory.py

  • Test: existing MCP auth/runtime tests

  • Step 1: Update SDK adapter imports

Modify src/wf_mcp/sdk/adapter.py.

Add import:

from ..auth import mcp_auth_env, mcp_auth_headers

Delete local _auth_headers.

In stdio branch, replace:

            if auth is not None:
                auth_env = auth.payload.get("env")
                if isinstance(auth_env, dict):
                    env = {**(env or {}), **auth_env}

with:

            auth_env = mcp_auth_env(auth)
            if auth_env:
                env = {**(env or {}), **auth_env}

In HTTP branch, replace:

            headers = _auth_headers(auth)

with:

            headers = mcp_auth_headers(auth)
  • Step 2: Update runtime factory imports

Modify src/wf_mcp/runtime/factory.py.

Add import:

from ..auth import mcp_auth_env, mcp_auth_headers

Delete local _auth_headers.

In stdio branch, replace:

            if auth is not None:
                auth_env = auth.payload.get("env")
                if isinstance(auth_env, dict):
                    env = {**(env or {}), **auth_env}

with:

            auth_env = mcp_auth_env(auth)
            if auth_env:
                env = {**(env or {}), **auth_env}

In HTTP branch, replace:

httpx.AsyncClient(headers=_auth_headers(auth) or None)

with:

httpx.AsyncClient(headers=mcp_auth_headers(auth) or None)
  • Step 3: Run focused tests

Run:

uv run pytest tests/wf_mcp/test_auth.py tests/wf_mcp/service/test_adapters.py tests/wf_mcp/service/test_workflow_runtime.py tests/wf_mcp/service/test_upstream_transport.py -q
uv run ruff check src/wf_mcp/auth.py src/wf_mcp/sdk/adapter.py src/wf_mcp/runtime/factory.py
uv run basedpyright --level error src/wf_mcp/auth.py src/wf_mcp/sdk/adapter.py src/wf_mcp/runtime/factory.py

Expected: all pass.

Task 6: Docs and final verification

Files:

  • Modify: docs/current_roadmap.md

  • Modify: docs/superpowers/specs/2026-06-06-auth-source-secrets-boundary.md

  • Step 1: Update roadmap status

In docs/current_roadmap.md, under the auth/source secrets boundary bullet, append:

    First implementation slice complete: neutral auth records/store protocol
    exist in `wf_api`, MCP runtime auth resolution prefers explicit `auth_ref`
    with legacy connection-id fallback, and MCP payload interpretation is
    isolated in provider-specific adapter helpers.
  • Step 2: Update spec status

In docs/superpowers/specs/2026-06-06-auth-source-secrets-boundary.md, add after ## Purpose:

## Status

Slice 1 implements the neutral auth record/store protocol and MCP compatibility
bridge. Diagnostics, auth admin surfaces, and provider-specific auth unions are
future slices.
  • Step 3: Run final verification

Run:

uv run pytest tests/wf_api/test_auth.py tests/wf_api/test_import_direction.py tests/wf_mcp/test_auth.py tests/wf_mcp/service/test_upstream_transport.py tests/wf_mcp/service/test_catalog.py tests/wf_mcp/service/test_workflow_runtime.py tests/wf_mcp/service/test_adapters.py -q
uv run ruff check src/wf_api src/wf_mcp tests/wf_api/test_auth.py tests/wf_mcp/test_auth.py tests/wf_mcp/service/test_upstream_transport.py
uv run basedpyright --level error src/wf_api src/wf_mcp tests/wf_api/test_auth.py tests/wf_mcp/test_auth.py tests/wf_mcp/service/test_upstream_transport.py

Expected: all pass.

  • Step 4: Final report

Report:

  • files created/modified
  • verification outputs
  • whether any old auth.payload[...] reads remain outside src/wf_mcp/auth.py
  • deviations from this plan

Search command for the payload check:

rg -n 'auth\.payload|get\("headers"|get\("token"|get\("env"' src/wf_mcp

Expected: payload interpretation is either in src/wf_mcp/auth.py or unrelated connection/source metadata handling. If adapter/runtime files still read auth.payload, fix before reporting.