mirror of
https://github.com/mcloh/Enterprise-MCP-Service-Bus.git
synced 2026-11-05 22:14:11 +00:00
revisão e complementação da documentação do projeto
This commit is contained in:
20
docs/adr/ADR-001-agent-privilege-ceiling.en-us.md
Normal file
20
docs/adr/ADR-001-agent-privilege-ceiling.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-001: MaximumEntitlement Boundary at the MCP Client
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Who defines the agent's privilege ceiling.
|
||||
|
||||
## Decision
|
||||
|
||||
MCP Client (authenticated identity) is the `MaximumEntitlement` boundary, never the agent/prompt.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Authorization by self-declared role of the agent.
|
||||
|
||||
## Consequences
|
||||
|
||||
All EP-01/EP-04 design revolves around the client's identity, not the agent's.
|
||||
20
docs/adr/ADR-002-enforcement-at-the-gateway.en-us.md
Normal file
20
docs/adr/ADR-002-enforcement-at-the-gateway.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-002: MCP Gateway as the sole PEP
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Where to apply enforcement.
|
||||
|
||||
## Decision
|
||||
|
||||
MCP Gateway is the sole PEP; it never delegates the ALLOW/DENY decision to the LLM.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Distributed enforcement in each MCP Server.
|
||||
|
||||
## Consequences
|
||||
|
||||
Centralizes EP-05; domain servers (EP-06) do not reimplement authz.
|
||||
20
docs/adr/ADR-003-reauthorization-of-tools-call.en-us.md
Normal file
20
docs/adr/ADR-003-reauthorization-of-tools-call.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-003: Independent reauthorization on tools/call
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Is filtered `tools/list` sufficient?
|
||||
|
||||
## Decision
|
||||
|
||||
No — `tools/call` must be reauthorized independently of discovery.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Relying only on filtered discovery.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-05 implements two enforcement points, not one.
|
||||
20
docs/adr/ADR-004-context-never-elevates-privilege.en-us.md
Normal file
20
docs/adr/ADR-004-context-never-elevates-privilege.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-004: Agentic context never elevates privilege
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Can agentic context elevate privilege?
|
||||
|
||||
## Decision
|
||||
|
||||
Never — context can only subtract (`Context may subtract, must never add`).
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Allowing elevation based on the model's "confidence."
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-15 tests (Test 3/4) validate the invariant.
|
||||
20
docs/adr/ADR-005-private-cache-for-tools-list.en-us.md
Normal file
20
docs/adr/ADR-005-private-cache-for-tools-list.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-005: Private cache for tools/list
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
`tools/list` cache shared across clients.
|
||||
|
||||
## Decision
|
||||
|
||||
`cacheScope=private`, key = identity+context+policy_version.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Shared cache for performance.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-05-T03; dedicated isolation test (EP-15).
|
||||
20
docs/adr/ADR-006-no-token-passthrough.en-us.md
Normal file
20
docs/adr/ADR-006-no-token-passthrough.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-006: Prohibition of token passthrough
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Can the agent's token be forwarded to the backend?
|
||||
|
||||
## Decision
|
||||
|
||||
No — blind token passthrough is prohibited; inbound ≠ outbound identity.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Direct passthrough of the client's token.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-07 implements exchange/service account per backend.
|
||||
20
docs/adr/ADR-007-backend-not-directly-exposed.en-us.md
Normal file
20
docs/adr/ADR-007-backend-not-directly-exposed.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-007: Backend never exposed directly to the client
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Is the backend directly accessible by the client?
|
||||
|
||||
## Decision
|
||||
|
||||
No — network/identity restrict access to the Gateway/Fabric only.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Exposing the Fabric publicly with "best effort" authz.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-05-T07, EP-15 (bypass test).
|
||||
20
docs/adr/ADR-008-segmentation-by-domain-and-risk.en-us.md
Normal file
20
docs/adr/ADR-008-segmentation-by-domain-and-risk.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-008: Client segmentation by domain and risk tier
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
How to segment clients.
|
||||
|
||||
## Decision
|
||||
|
||||
By domain + risk tier (R0–R4), not a single global client.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
A single "enterprise admin" client.
|
||||
|
||||
## Consequences
|
||||
|
||||
Defines P6 (granularity) and EP-04.
|
||||
20
docs/adr/ADR-009-risk-tiers-for-capabilities.en-us.md
Normal file
20
docs/adr/ADR-009-risk-tiers-for-capabilities.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-009: Risk tiers R0-R4 for capabilities
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
How to classify capabilities.
|
||||
|
||||
## Decision
|
||||
|
||||
Risk tiers R0–R4 in the Registry, controlling required approval/observability.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
No formal classification.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-02-T01 includes mandatory `risk_tier` in the manifest schema.
|
||||
20
docs/adr/ADR-010-registry-governance.en-us.md
Normal file
20
docs/adr/ADR-010-registry-governance.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-010: Governance of the Global Capability Registry
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Governance of the Global Capability Registry (title and number inherited from §49 of the README — "Global Capability Registry Governance").
|
||||
|
||||
## Decision
|
||||
|
||||
The Registry is a control-plane asset (§6.6) with its own authority and lifecycle, separate from the catalog view delivered to each client. In the RI: dedicated storage and read API (EP-02-T03), consumed by Gateway/Fabric/Offering Filter but never edited by them; formal lifecycle nominate→review→register→publish→observe→(change|deprecate→retire) (§23) implemented as a state machine (EP-02-T04); every change goes through the publishing pipeline (EP-02-T02) — no direct manual registration in production (RF-11). The Registry's organizational owner (who approves schema/policy changes to the control plane itself) remains a corporate governance decision outside the technical scope of the RI (§48, question 4, still open).
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Leaving the Registry as a table editable ad hoc by any service; merging the control view (Registry) with the execution view (catalog filtered per client), which would violate the control plane/data plane separation of §24.
|
||||
|
||||
## Consequences
|
||||
|
||||
The entire EP-02; reinforces that EP-05 (Gateway) and EP-10 (Offering Filter) only read the Registry, never write to it.
|
||||
20
docs/adr/ADR-011-publishing-pipeline.en-us.md
Normal file
20
docs/adr/ADR-011-publishing-pipeline.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-011: Mandatory pipeline for capability publication
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Capability publication cycle.
|
||||
|
||||
## Decision
|
||||
|
||||
Mandatory pipeline with schema/risk/policy/health gates before entering the Registry — no manual registration in production.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Direct registration via administrative API without a pipeline.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-02-T02 implements the gate; no capability is "born" already published.
|
||||
20
docs/adr/ADR-012-entitlement-manager-as-authority.en-us.md
Normal file
20
docs/adr/ADR-012-entitlement-manager-as-authority.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-012: Entitlement Manager as the sole authority for MaximumEntitlement
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, where applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Authority over the maximum menu.
|
||||
|
||||
## Decision
|
||||
|
||||
Entitlement Manager is the sole authority for `MaximumEntitlement`; it does not rank nor trust self-declared attributes from the LLM.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Merging Entitlement Manager and Offering Filter into a single component.
|
||||
|
||||
## Consequences
|
||||
|
||||
Keeps EP-04 and EP-10 as distinct services/modules with their own contracts.
|
||||
20
docs/adr/ADR-013-profile-intelligence-contract.en-us.md
Normal file
20
docs/adr/ADR-013-profile-intelligence-contract.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-013: Pluggable Profile Intelligence contract
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Profile Intelligence contract.
|
||||
|
||||
## Decision
|
||||
|
||||
Generic, replaceable interface (versioned `ProfileView`, with `reasonCodes`), pluggable implementation.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Coupling to a specific vendor/taxonomy for segmentation.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-09 defines only the contract + reference stub (see P7).
|
||||
20
docs/adr/ADR-014-profile-never-expands-entitlement.en-us.md
Normal file
20
docs/adr/ADR-014-profile-never-expands-entitlement.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-014: Profile never expands entitlement
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Can profile expand entitlement?
|
||||
|
||||
## Decision
|
||||
|
||||
Never — `FilteredOfferings ⊆ MaximumEntitlement`, profile only orders/reduces.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
High-engagement profile unlocking new tools.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-10-T02 brings a property test validating the invariant for random inputs.
|
||||
20
docs/adr/ADR-015-nba-is-not-authorization.en-us.md
Normal file
20
docs/adr/ADR-015-nba-is-not-authorization.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-015: NBA as an orchestration decision, not an authorization decision
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Is NBA an authorization decision?
|
||||
|
||||
## Decision
|
||||
|
||||
No — it is orchestration intent; Gateway/PDP reauthorize every execution.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Orchestrator dispatching directly to the backend without going through the Gateway.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-11-T04 implements the DENY/recalculation branch of §10.1.
|
||||
20
docs/adr/ADR-016-dispatch-handoff-contract.en-us.md
Normal file
20
docs/adr/ADR-016-dispatch-handoff-contract.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-016: Agent Runtime dispatch/handoff contract
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Agent Runtime dispatch/handoff contract.
|
||||
|
||||
## Decision
|
||||
|
||||
Versioned dispatch object (`decisionId`, `expiresAt`, `reasonCodes`) that does not replace the MCP Client's token.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Runtime injecting its own credentials into the agent.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-12-T01 consumes exclusively the dispatch object + the already-existing MCP Client.
|
||||
20
docs/adr/ADR-017-end-to-end-correlation.en-us.md
Normal file
20
docs/adr/ADR-017-end-to-end-correlation.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-017: End-to-end correlation via versioned IDs
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
End-to-end correlation.
|
||||
|
||||
## Decision
|
||||
|
||||
`profileVersion`+`entitlementVersion`+`decisionId`+`policyDecisionId`+`mcpRequestId` propagated via OTel/trace context across all components.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Correlation only via free-text logs with no standard.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-08-T03 formalizes the fields; basis for EP-15 (auditability).
|
||||
58
docs/adr/ADR-018-implementation-stack.en-us.md
Normal file
58
docs/adr/ADR-018-implementation-stack.en-us.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# ADR-018: RI implementation stack
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
RI implementation stack (closes G2).
|
||||
|
||||
## Decision
|
||||
|
||||
Python 3.12+, `uv`, Pydantic v2, declarative YAML with JSON Schema, official `mcp` SDK.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Node/TypeScript (the MCP SDK is also official there); Go.
|
||||
|
||||
## Consequences
|
||||
|
||||
Defines the entire repository structure (8.5).
|
||||
|
||||
## Confirmed Versions (EP-16-T04)
|
||||
|
||||
Dependency-free spike, runnable at any time (EP-16-T04): confirm,
|
||||
immediately before pinning in `pyproject.toml`/
|
||||
`docker-compose.yml`, the exact stable version numbers of each piece of the
|
||||
stack — no version cited in code/config without real confirmation
|
||||
(`pip index versions`/direct download/actual install), never from memory.
|
||||
Consolidated record, with the date each group was verified (see
|
||||
`RI/README.md`, "Versões fixadas", for the same list maintained alongside
|
||||
`pyproject.toml`):
|
||||
|
||||
Confirmed on 2026-09-11:
|
||||
|
||||
- `mcp` 2.2.0 (Python SDK v2 — the API changed significantly from v1; see
|
||||
comments in `src/emcp_bus/gateway/server.py`)
|
||||
- `pydantic` 2.13.x, `opentelemetry-sdk` 1.44.x, `uvicorn` 0.52.x,
|
||||
`pyjwt[crypto]` 2.14.x, `ruff` 0.16.x, `mypy` 2.3.x, `pytest` 9.1.x
|
||||
- `OPA` 1.20.2 (static binary, Rego v1 syntax as default)
|
||||
- `pytest-forked` 1.7.x
|
||||
|
||||
Confirmed on 2026-09-14 (M3/M4, via actual install/`docker pull`):
|
||||
|
||||
- `langgraph` 0.6.x + `langgraph-checkpoint-sqlite` 2.x (EP-11)
|
||||
- `hypothesis` 6.1xx.x (dev, EP-10-T02)
|
||||
- `openai` 1.109.x (EP-13-T01)
|
||||
- `python-dotenv` 1.2.x (dev)
|
||||
- `types-jsonschema` 4.26.x (dev, stubs for `mypy --strict`; `jsonschema`
|
||||
itself was already a transitive dependency of `mcp[cli]`, EP-15-T01)
|
||||
- Langfuse self-hosted 4.35.0 (`docker.langfuse.com/langfuse/langfuse:4`,
|
||||
official image, EP-13-T02)
|
||||
- Keycloak 26.7.3 (`quay.io/keycloak/keycloak:26.7.3`, Quarkus; Standard
|
||||
Token Exchange GA since 26.2 — EP-01-T01/EP-07)
|
||||
- `opentelemetry-collector-contrib` 0.114.0 and `jaeger` (all-in-one) 1.62.0
|
||||
(`observability` profile of `docker-compose.yml`, EP-08-T04)
|
||||
|
||||
None of the versions above have changed since the original confirmation — this
|
||||
record is the single source of truth that `RI/README.md` links back to.
|
||||
106
docs/adr/ADR-019-extensao-de-identidade.md
Normal file
106
docs/adr/ADR-019-extensao-de-identidade.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# ADR-019: Identidade do MCP Client -- ponto de extensão de produção (mTLS / workload identity)
|
||||
|
||||
**Status:** Documentado (spike), não implementado na RI (EP-01-T04, `could`).
|
||||
**Fonte:** este ADR é o registro canônico desta decisão. Para contexto de implementação e validação, ver `RI/docs/AS-BUILT.md` e, quando aplicável, o contrato relevante em `RI/docs/interfaces/identity-oidc.md`. Também relevante: README.md §19, RF-02, Axiom 2.
|
||||
|
||||
## Contexto
|
||||
|
||||
A fronteira de identidade da RI (`src/emcp_bus/identity/authn.py`, EP-01-T03) é
|
||||
OAuth 2.1 `client_credentials` contra o Keycloak (EP-01-T01): todo MCP Client
|
||||
se autentica com um client_id + secret, obtém um JWT de vida curta, e o
|
||||
Gateway valida a assinatura/emissor/audience/expiração desse JWT contra o
|
||||
JWKS do IdP antes de confiar na claim `azp` como a identidade do caller.
|
||||
|
||||
Esta é uma decisão deliberada e confirmada para a RI (não um placeholder): OAuth
|
||||
2.1 satisfaz toda propriedade que o README.md §19 de fato exige de um mecanismo
|
||||
de identidade -- vida curta, revogável, vinculado a uma audience, verificável
|
||||
sem um segredo de longo prazo compartilhado no caminho da requisição.
|
||||
Implantações corporativas reais comumente vão além, usando mTLS (certificados
|
||||
de cliente TLS mútuo) ou a federação de workload identity de um provedor de
|
||||
nuvem (ex.: SPIFFE/SPIRE, AWS IAM roles for service accounts, GCP Workload
|
||||
Identity, Azure Managed Identity) em vez de -- ou além de -- um JWT bearer.
|
||||
Este ADR documenta como essa extensão se encaixa na costura já existente da
|
||||
RI, sem exigi-la, para que um fork de produção não fique bloqueado por um
|
||||
redesenho.
|
||||
|
||||
## Decisão
|
||||
|
||||
**Não** implementar mTLS/workload identity na RI. Documentar o ponto de
|
||||
extensão em vez disso, para que o contrato do `EP-01-T03` seja
|
||||
comprovadamente estável sob ele.
|
||||
|
||||
## O ponto de extensão
|
||||
|
||||
`TokenValidator.validate(token: str) -> AuthenticatedClient` é a *única*
|
||||
função na RI que produz identidade de client para fins de autorização
|
||||
(`emcp_bus.gateway.server.on_list_tools`/`on_call_tool` chamam ambos
|
||||
`get_access_token()`, que é populado pelo protocolo `TokenVerifier` do SDK
|
||||
envolvendo esse mesmo validator -- ver
|
||||
`emcp_bus.identity.token_verifier.MCPTokenVerifier`). Tudo a jusante dela --
|
||||
`EntitlementManager.resolve`, o PDP, a camada de audit/correlação (EP-08) --
|
||||
consome apenas o `AuthenticatedClient.client_id` resultante. Nenhum desse
|
||||
código se importa com *como* a identidade foi estabelecida.
|
||||
|
||||
Uma implantação de produção adicionando mTLS ou workload identity faria:
|
||||
|
||||
1. Implementar uma segunda fonte de identidade honrando o mesmo contrato de saída:
|
||||
|
||||
```python
|
||||
class MTLSClientValidator:
|
||||
def validate(self, request: ...) -> AuthenticatedClient: ...
|
||||
```
|
||||
|
||||
alimentada pelo certificado de cliente já verificado pelo proxy/load
|
||||
balancer que termina a conexão (um header estilo `X-Client-Cert-CN` de um
|
||||
terminador mTLS confiável, ou o `scope["extensions"]["tls"]` ASGI que um
|
||||
servidor compliant expõe) em vez de um JWT. `AuthenticatedClient.client_id`
|
||||
seria o Subject/SAN do certificado, mapeado 1:1 a um
|
||||
`ClientRegistration.client_id` exatamente da mesma forma que o `azp` de um
|
||||
JWT é hoje -- **nenhum outro modelo da RI muda**: `ClientRegistration`,
|
||||
`ClientProfile`, `EntitlementManager`, o contrato do PDP e o schema de
|
||||
auditoria já são todos agnósticos de mecanismo de identidade.
|
||||
|
||||
2. Fornecer um equivalente alternativo de `build_auth()` em
|
||||
`emcp_bus/gateway/server.py` que conecta o novo validator no lugar de
|
||||
`MCPTokenVerifier`, controlado por configuração de deployment -- o mesmo
|
||||
formato do `build_auth()` de hoje retornando `(None, None)` para o modo
|
||||
"sem OIDC configurado". Uma implantação híbrida (mTLS para uma classe de
|
||||
backend service, OAuth para agentes interativos) é possível fazendo a
|
||||
seleção de `TokenVerifier`/equivalente por listener em vez de por
|
||||
processo, o que os parâmetros
|
||||
`streamable_http_app(auth=..., token_verifier=...)` do SDK já suportam
|
||||
por instância de app.
|
||||
|
||||
3. Workload identity de nuvem (SPIFFE/SPIRE, IRSA, Workload Identity, Managed
|
||||
Identity) é uma variante da mesma forma: o contrato "verificar uma
|
||||
credencial que o caller não pode forjar, e extrair dela um identificador
|
||||
estável" é idêntico, só o formato da credencial e a biblioteca de
|
||||
verificação diferem. Nada disso exige tocar no `EntitlementManager`, no
|
||||
PDP, no roteador do Fabric (EP-06-T01), ou na camada de audit/correlação
|
||||
(EP-08-T02/T03).
|
||||
|
||||
## O que não pode mudar
|
||||
|
||||
- **Formato de `AuthenticatedClient`** (`client_id`, `issuer`, `expires_at`):
|
||||
todo consumidor a jusante tipa contra isso, não contra um conjunto de
|
||||
claims específico de JWT.
|
||||
- **Contrato fail-closed**: o caminho de falha de qualquer mecanismo de
|
||||
identidade deve levantar uma exceção (no formato `AuthenticationError`) em
|
||||
vez de recair para uma identidade não autenticada ou autodeclarada pelo
|
||||
agente (README.md §5, Axiom 2) -- essa é a propriedade de segurança real
|
||||
que o critério de aceite do EP-01-T03 testa, e ela é independente de
|
||||
mecanismo.
|
||||
- **Nenhum caminho privilegiado novo para `clientInfo`**: qualquer que seja o
|
||||
mecanismo de identidade, apenas um valor verificado de forma independente
|
||||
do corpo da requisição MCP pode popular `client_id`.
|
||||
|
||||
## Consequências
|
||||
|
||||
- Confirmado para a RI: reduz o esforço de implementação do EP-01 sem
|
||||
enfraquecer nenhuma das propriedades de identidade desejáveis do README.md
|
||||
§19 (todas satisfeitas por OAuth 2.1 `client_credentials` contra o
|
||||
Keycloak).
|
||||
- Um fork de produção adicionando mTLS/workload identity muda exatamente um
|
||||
módulo (`identity/`) e uma função de wiring (equivalente a `build_auth`);
|
||||
todo outro componente da RI (Entitlement Manager, PDP, Fabric, Registry,
|
||||
audit/correlação, approval) não exige nenhuma mudança.
|
||||
20
docs/adr/ADR-020-downstream-identity.en-us.md
Normal file
20
docs/adr/ADR-020-downstream-identity.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-020: Downstream identity: token exchange or isolated service account
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Downstream identity in the RI (closes G5/P5).
|
||||
|
||||
## Decision
|
||||
|
||||
Token exchange (RFC 8693) when the backend supports OIDC; otherwise a service account isolated per adapter.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Always reusing the client's token (forbidden by ADR-006).
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-07; documented per backend in the manifest.
|
||||
20
docs/adr/ADR-021-langgraph-langfuse-scope.en-us.md
Normal file
20
docs/adr/ADR-021-langgraph-langfuse-scope.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-021: Scope of LangGraph and Langfuse in the RI
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Scope of LangGraph/Langfuse (closes G8/P8).
|
||||
|
||||
## Decision
|
||||
|
||||
LangGraph only in the Service Orchestrator (EP-11) and the Agent Runtime handoff (EP-12); Langfuse only where there is an actual LLM call (EP-13). Checkpointer: SQLite in dev.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Also using LangGraph in the Gateway/Fabric for "stack consistency."
|
||||
|
||||
## Consequences
|
||||
|
||||
Avoids the over-engineering vetoed by section 6 of the superprompt; Gateway/Fabric remain plain Python.
|
||||
@@ -0,0 +1,20 @@
|
||||
# ADR-022: Operational reference: Agent Platform OCI (Hoshikawa)
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Concrete Python/LangGraph/Langfuse implementation reference (closes G2 — **decision confirmed by the author on 2026-09-11**).
|
||||
|
||||
## Decision
|
||||
|
||||
Adopt as an operational reference the "Agent Platform OCI" by Christiano Hoshikawa (`github.com/hoshikawa2/agent_platform_oci`): a StateGraph with a router/supervisor per backend + an upper routing layer across backends (our EP-11/EP-12); pluggable checkpointing (memory/sqlite/mongodb/production — we adopt SQLite in dev, see ADR-021); **IC/NOC/GRL** observability taxonomy via Langfuse (business/operational/guardrail event), with hybrid instrumentation (automatic span per node + manual fail-open emission); `identity.yaml`/`BusinessContext` to normalize business identity across channels; FastMCP as the standard MCP server. Full analysis recorded in `docs/research/hoshikawa-agent-platform-oci.md`.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Continuing with the generic pattern from section 6 of the superprompt without a concrete third-party reference (slower, more ad hoc decisions); adopting a market agent framework (CrewAI, AutoGen) instead of plain LangGraph.
|
||||
|
||||
## Consequences
|
||||
|
||||
Changes the form (not the security) of EP-08, EP-11, EP-12, EP-13 — see ADR-023 for the explicit boundary of what is NOT adopted.
|
||||
@@ -0,0 +1,20 @@
|
||||
# ADR-023: Tool authorization never comes from a field declared in the payload
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
Tool authorization NEVER comes from a field declared in the payload/conversation (a critical finding from the Hoshikawa analysis, reinforcing ADR-001/002/003).
|
||||
|
||||
## Decision
|
||||
|
||||
The Agent Platform OCI's MCP Gateway authorizes tools via a static allowlist (`tools.yaml`/`authorization.agents.<agent_id>.allowed_tools`) evaluated over `agent_id`, a field that arrives as **data from the conversation's input payload**, not as a claim from an independently verified authenticated identity — their own SPEC-004 admits that this does not replace real authentication/authorization. Our RI reuses the proxy *form* of this MCP Gateway (`ToolInvocation`/`ToolResult` contracts, idempotent per-tool cache, `/v1/tools` catalog) **exclusively at the Fabric layer (EP-06)/conversational UX**, but the ALLOW/DENY decision remains 100% in our PEP (EP-05) consulting the PDP (EP-03) with the authenticated identity of the MCP Client (EP-01) — never with a self-declared `agent_id`/`tenant_id` in the payload.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Also reusing their `authorization` block as an implementation shortcut.
|
||||
|
||||
## Consequences
|
||||
|
||||
EP-15-T03 gains an explicit adversarial "payload-declared agent_id spoofing" scenario (a variation of Test 4, §45) to prove that this specific vector is closed in our RI.
|
||||
20
docs/adr/ADR-024-multiagent-positioning.en-us.md
Normal file
20
docs/adr/ADR-024-multiagent-positioning.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-024: E-MCP-BUS positioning relative to external multi-agent platforms
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
E-MCP-BUS positioning relative to external multi-agent orchestration platforms, such as Agent Platform OCI (**decision confirmed and expanded by the author on 2026-09-11** — resolves G11).
|
||||
|
||||
## Decision
|
||||
|
||||
E-MCP-BUS **does not compete** with orchestration platforms such as Agent Platform OCI — but it also **is not limited to coexisting under them**. Explicit design principle: **modularity + compatibility = choice**. Our Service Orchestrator (EP-11) is not a thin pass-through: it computes NBA **and NBO** (Next Best Action/Next Best Offer) with its own decision model (rules + guardrails +, optionally, a ranking/recommendation AI model — see EP-11-T03) over the universe of `FilteredOfferings` that the MCP Fabric exposes (services, offers, actions, campaigns — not just technical "tools"). This enables **two equally valid integration modes, chosen by the adopter according to the desired topology**: **(A) Governance-only** — an external orchestration platform (e.g., Agent Platform OCI, with its own Global Supervisor and StateGraph deciding NBA) connects to E-MCP-BUS solely for governed access to the Fabric; our Service Orchestrator does not participate, or participates only as a source of `FilteredOfferings` (as already described in the rest of this ADR and in EP-13-T05). **(B) Full replacement** — our own Service Orchestrator (EP-11) fully takes on the role of the decision "brain" (NBA/NBO), dispensing with the external platform's decision-making Global Supervisor/StateGraph; the Agent Runtime (EP-12) and the external platform's channel adapters (e.g., Hoshikawa's agent backends) become mere executors of the dispatch our Orchestrator produces. In either mode, the security core (PEP/PDP, EP-05/EP-03) never changes place — only who computes the NBA/NBO changes. In both modes, each domain backend/agent remains registered as a **distinct MCP Client** (EP-01), bound to its own client profile/entitlement per domain+risk tier (EP-04, P6), and any consuming platform's internal "MCP Gateway" (ADR-023) is always superseded by our Gateway/PEP as the single point of authorization. This is the "Enterprise elevation": centrally governed catalog/entitlement/audit, with the NBA/NBO decision able to come from inside (mode B) or outside (mode A) the bus, by the adopter's modular choice.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Forcing a single integration mode (e.g., only "governance-only"), which would underuse the Service Orchestrator and always require an external decision platform; treating Agent Platform OCI as a substitute for E-MCP-BUS (incorrect — it does not solve entitlement); reimplementing from scratch the orchestration engineering already validated in ADR-022 even when mode B is chosen (the StateGraph/checkpointing/handoff form remains reusable within our EP-11/EP-12).
|
||||
|
||||
## Consequences
|
||||
|
||||
Reshapes the goal of EP-11 (Service Orchestrator explicitly described as computing NBA **and NBO** over Fabric services/offers/actions, with a pluggable decision model) and of EP-13 (demonstrates the two modes — see EP-13-T05 for mode A and EP-13-T06, new, for mode B). Reinforces that EP-06/EP-05 treat any consuming platform's "MCP Gateway" as untrusted for authorization, in both modes.
|
||||
20
docs/adr/ADR-025-pdp-engine.en-us.md
Normal file
20
docs/adr/ADR-025-pdp-engine.en-us.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ADR-025: OPA/Rego as the PDP engine
|
||||
|
||||
**Status:** Accepted.
|
||||
**Source:** this ADR is the canonical record of this decision. For implementation and validation context, see `RI/docs/AS-BUILT.md` and, when applicable, the relevant contract in `RI/docs/interfaces/`.
|
||||
|
||||
## Context
|
||||
|
||||
PDP engine (closes G3 — **decision confirmed by the author on 2026-09-11**; renumbered from ADR-010 to ADR-025 on 2026-09-11 to avoid colliding with the README's ADR-010, "Global Capability Registry Governance").
|
||||
|
||||
## Decision
|
||||
|
||||
OPA/Rego, self-hosted, OSS (Apache-2.0). Final decision, not subject to review. **Verified on 2026-09-11 via web search**: OPA is at v1.0+, with Rego v1 syntax as the default (a breaking change vs. v0) — EP-03 must write policies in Rego v1 syntax from the start.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
Cedar (AWS, cited in §43.2); a custom engine in Python.
|
||||
|
||||
## Consequences
|
||||
|
||||
The entire EP-03 becomes coupled to OPA's REST API; policies versioned as code in Rego v1.
|
||||
Reference in New Issue
Block a user