Add service-context login policy enforcement

Services send service_name and tags in POST /v1/auth/login.
MCIAS evaluates auth:login policy with these as the resource
context after credentials are verified, enabling rules like:
  deny guest/viewer human accounts from env:restricted services
  deny guest accounts from specific named services

- loginRequest: add ServiceName and Tags fields
- handleLogin: evaluate policy after credential+TOTP check;
  policy deny returns 403 (not 401) to distinguish access
  restriction from bad credentials
- Go client: Options.ServiceName/Tags stored on Client,
  sent automatically in every Login() call
- Python client: service_name/tags on __init__, sent in login()
- Rust client: ClientOptions.service_name/tags, LoginRequest
  fields, Client stores and sends them in login()
- openapi.yaml: document service_name/tags request fields
  and 403 response for policy-denied logins
- engineering-standards.md: document service_name/tags in
  [mcias] config section with policy examples

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-16 21:09:38 -07:00
parent b0afe3b993
commit 39d9ffb79a
5 changed files with 136 additions and 12 deletions

View File

@@ -567,6 +567,12 @@ paths:
If the account has TOTP enrolled, `totp_code` is required.
Omitting it returns HTTP 401 with code `totp_required`.
`service_name` and `tags` identify the calling service. MCIAS
evaluates `auth:login` policy against these values after credentials
are verified. A policy-denied login returns HTTP 403 (not 401) so
callers can distinguish a service access restriction from bad credentials.
Clients should populate these from their `[mcias]` config section.
operationId: login
tags: [Public]
requestBody:
@@ -587,6 +593,21 @@ paths:
type: string
description: Current 6-digit TOTP code. Required if TOTP is enrolled.
example: "123456"
service_name:
type: string
description: >
Name of the calling service. Used by MCIAS to evaluate
auth:login policy rules that target specific services.
example: metatron
tags:
type: array
items:
type: string
description: >
Tags describing the calling service (e.g. "env:restricted").
MCIAS evaluates auth:login policy rules with required_tags
against this list.
example: ["env:restricted"]
responses:
"200":
description: Login successful. Returns JWT and expiry.
@@ -607,6 +628,17 @@ paths:
value: {error: invalid credentials, code: unauthorized}
totp_required:
value: {error: TOTP code required, code: totp_required}
"403":
description: >
Login denied by policy. Credentials were valid but an operator
policy rule blocks this account from accessing the calling service.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
examples:
policy_denied:
value: {error: access denied by policy, code: policy_denied}
"429":
$ref: "#/components/responses/RateLimited"