feat(standards): integrate auth-server via pinned spec (docs://spec) + auth recipe and template slice

- serve the pinned auth-server OpenAPI contract as the standards MCP resource docs://spec (no auth-server MCP bundle)
- add Auth Integration recipe (14) and wire it into the registry, prompts, index, and nav
- un-defer Auth Server in the library registry (spec/recipe pointers)
- ship the opt-in template auth slice: interfaces/auth/ (placeholder + mergeable bearerAuth security.yaml) and AUTH_SERVER/JWT_SERVER env
- rebuild bundle (13 modules, 44 components); template stays authless by default
This commit is contained in:
2026-10-14 16:18:14 +05:30
parent 6c0d859a1e
commit 18d52bdb7c
37 changed files with 2094 additions and 24 deletions

View File

@@ -7,6 +7,7 @@ template code — before writing any infrastructure.
Resources:
docs://index, docs://nav, docs://modules/{module} (from the base server)
docs://spec (the pinned auth-server OpenAPI contract)
registry://libraries (the structured catalog)
registry://components (the template component index)
@@ -46,7 +47,8 @@ _INTAKE_TEXT = (
"2. Axis 1 — resources: each resource, its fields, and relationships\n"
" (or paste `openapi.yaml`).\n"
"3. Axis 2 — pipelines: multi-step inputs? families + formats (or `none`).\n"
"4. Auth needed now? (yes/no; auth is deferred — `py-jwt` only).\n"
"4. Auth needed now? (yes/no). If yes, the auth-server service provides it —\n"
" read `docs://spec` + `docs://modules/auth_integration` (no auth code to write).\n"
"5. Integrations: Mongo / ingestion formats / email / LLM provider.\n\n"
"Then: `build(app_name=..., resources=..., pipelines=..., auth=...)`.\n"
)
@@ -79,7 +81,10 @@ def _build_text(app_name: str, resources: str, pipelines: str, auth: str) -> str
"4. Scaffold with `get_app_template()` (whole tree) or pull single "
"files with `list_app_components()` and "
"`get_app_component(kind, resource=..., family=...)`.\n"
"5. Author only Tier C; keep Tier B as shipped.\n"
"5. If auth is needed, read `docs://spec` (the auth-server contract) and "
"`docs://modules/auth_integration`; declare `securitySchemes.bearerAuth` "
"and `security` in your spec — do not write auth code.\n"
"6. Author only Tier C; keep Tier B as shipped.\n"
)
@@ -114,6 +119,13 @@ class StandardsMCPServer(MCPServer):
return {"error": "not_found", "path": str(path), "components": []}
return json.loads(path.read_bytes())
def _spec(self) -> dict[str, Any]:
"""Load the pinned OpenAPI contract (auth-server)."""
path = Path(self.mcp_root) / "specs" / "auth-server.json"
if not path.exists():
return {"error": "not_found", "path": str(path)}
return json.loads(path.read_bytes())
def _find_component(self, kind: str) -> dict[str, Any] | None:
for entry in self._components().get("components", []):
if entry.get("kind") == kind:
@@ -183,6 +195,15 @@ class StandardsMCPServer(MCPServer):
def components() -> dict[str, Any]:
return self._components()
@self.app.resource("docs://spec")
def spec() -> dict[str, Any]:
"""Return the pinned auth-server OpenAPI contract.
Use this (instead of a live fetch) to learn the auth-server client
contract when wiring authentication into an app.
"""
return self._spec()
@self.app.tool()
def find_library(capability: str) -> list[dict[str, Any]]:
"""Find internal libraries matching a capability keyword.
@@ -211,6 +232,8 @@ class StandardsMCPServer(MCPServer):
str(lib.get("import", "")),
str(lib.get("purpose", "")),
str(lib.get("use_instead_of", "")),
str(lib.get("spec", "")),
str(lib.get("recipe", "")),
" ".join(lib.get("capabilities", [])),
]
).lower()