Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/joseluis-dev/harness-ai/llms.txt

Use this file to discover all available pages before exploring further.

Phase 1 connects Harness AI to the institutional identity system so that every action the harness takes is attributed to a real user with verified roles and department membership. Without this phase, audit records carry no meaningful actor context, and the harness cannot distinguish between an authorized administrator and an unauthenticated caller. Phase 1 is also a hard dependency for Phase 8 (Telegram seguro), which must map a telegram_user_id to an institutional identity before any command is processed.

Objective

Connect the harness to the external institutional identity system so that each action is attributed to a real user with their roles and department, and so that sensitive actions are blocked when identity cannot be validated. The fail-closed principle (AD-5) applies without exception: when the identity system is unavailable, sensitive writes are denied — there is no anonymous fallback.

Dependencies

  • Phase 0 (Base executable local) — the monorepo, executions/audit_events tables, and the runtime Python worker must already be running.

What to Implement

mcp-identity-connector

Service (or CLI/API adapter) that exposes four endpoints: validate_session, get_user_context, get_user_permissions, and get_department_users. This is the canonical interface for all phases that need to resolve an actor.

Astro middleware integration

Middleware in harness-core that calls mcp-identity-connector on every inbound request to resolve the session into an actor context before the request handler runs.

User context cache

Short-lived cache for resolved actor contexts to avoid a round-trip to the identity system on every request. Cache entries must be invalidated when permissions change.

Basic permissions

Role-based permission checks wired to the actor context. The risk_level of an action is compared against the actor’s resolved roles; a mismatch blocks the action.

Identity audit

Every identity resolution (successful or failed) is written to audit_events with actor_id, department, roles, and the outcome (resolved / failed / denied).

Fail-closed gate

When mcp-identity-connector is unreachable or returns an error, any action with risk_level ∈ {high, critical} is blocked immediately. No fallback to anonymous context is permitted.

Key Design Decisions

Actor Context Shape

Every resolved identity produces a structured actor context forwarded to all downstream systems. The actor_type field takes one of three values: user (for resolved institutional users), system (for automated background processes such as the document watcher), or service (for technical OAuth clients). System and service actors may not trigger sensitive writes.
{
  "actor_type": "user",
  "actor_id": "usr_abc123",
  "user_id": "jlopez",
  "department": "urbanismo",
  "roles": ["consultor", "aprobador_expedientes"]
}
System-initiated actions (e.g. the document watcher) use actor_type: "system" with a fixed actor_id; they may not trigger sensitive writes. Service-to-service calls use actor_type: "service".

Identity Forwarding Headers

When harness-core proxies requests to internal services, it attaches the resolved identity as HTTP headers. Both headers are capped at 128 characters (ACTOR_FIELD_MAX_LENGTH = 128). Values longer than 128 characters are rejected before forwarding:
HeaderContentMax length
X-Harness-Actor-IdResolved actor_id128 chars
X-Harness-Actor-DepartmentResolved department128 chars
These headers must never be accepted from external clients — they are set exclusively by Harness Core middleware after resolution.

Sensitive Request Predicate (isSensitiveRequest)

The middleware applies the following predicate to determine whether a request requires verified identity before proceeding:
isSensitiveRequest: method == POST AND path == /api/executions AND risk_level ∈ {high, critical}
If all three conditions are met and the identity system is unavailable, the request is rejected with 401 identity_unavailable before any agent, model, or tool is invoked.

Fail-Closed Gate (AD-5)

The fail-closed rule is absolute. If the identity system is unavailable and an execution request carries risk_level: high or risk_level: critical, the request is rejected before any agent, model, or tool is invoked:
# Simulating identity system unavailable + high risk_level
curl -fsS -X POST http://localhost:4321/api/executions \
  -H "Content-Type: application/json" \
  -d '{
    "source_type": "manual",
    "intent": "sensitive-operation",
    "risk_level": "high"
  }'
Expected response — HTTP 401:
{
  "error": "identity_unavailable",
  "message": "Identity system unreachable. Sensitive actions require verified identity.",
  "code": "IDENTITY_UNAVAILABLE"
}
The identity_unavailable error code must appear in audit_events whenever this gate fires — the absence of an audit event for a blocked attempt is itself a policy violation. Low-risk executions (risk_level: low) may proceed with a degraded anonymous actor context when the identity system is temporarily unavailable — but this behavior must be explicitly configured per deployment and is off by default.

Acceptance Criteria

1

Real user identified — no placeholder or anonymous actor

The harness resolves the user from the external identity system. The resolved actor_id is not a placeholder string such as "anonymous", "unknown", or an empty value. Every inbound request that reaches an execution endpoint must carry a resolved actor context before the handler runs.
2

Roles and department resolved from the external system

mcp-identity-connector.get_user_context(actor_id) returns the user’s roles and department from the institutional directory — not from a local database or hardcoded values. The returned context populates executions.user_id and executions.department.
3

Executions record user_id and department

After an execution is created, the executions row reflects the resolved identity:
curl -fsS http://localhost:4321/api/executions/${EXEC_ID}
{
  "id": "5b47cba7-...",
  "status": "completed",
  "user_id": "jlopez",
  "department": "urbanismo"
}
4

Fail-closed: sensitive actions blocked when identity system fails

Bring down mcp-identity-connector (or simulate a 503) and issue a high-risk execution request. The response must be 401 identity_unavailable with no execution row created. Check audit_events to confirm the blocked attempt was recorded with error: "identity_unavailable".
5

mcp-identity-connector.get_user_context available as API

Other phases — especially Phase 8 (Telegram seguro) — must be able to call mcp-identity-connector.get_user_context(actor_id) directly via its internal HTTP API. Confirm the endpoint responds:
curl -fsS http://mcp-identity-connector:8001/get_user_context \
  -H "Content-Type: application/json" \
  -d '{"actor_id": "jlopez"}'
Expected — the user context shape documented above, with actor_type set to "user" for institutional users.

Operational Notes

The fail-closed rule is non-negotiable. Never add a code path that falls back to an anonymous identity for risk_level ∈ {high, critical} actions. The correct response to an identity system failure is a clear identity_unavailable error — not silent degradation.
  • The four mcp-identity-connector endpoints (validate_session, get_user_context, get_user_permissions, get_department_users) are the only authorized way to resolve institutional identity. No phase may query an external LDAP, AD, or SSO system directly.
  • Phase 1 is a prerequisite for Phases 2, 3, 4, 5, 6, 8, 9, and 11. It is the second most critical phase after Phase 0.
  • Identity audit records in audit_events are mandatory. A failed identity resolution must produce an audit event — the absence of an event is itself a policy violation.
  • ACTOR_FIELD_MAX_LENGTH = 128 applies to both actor_id and department values forwarded in HTTP headers. Values exceeding this limit are rejected before any downstream call is made.
See Harness Core — Middleware for the full middleware implementation details, including the session cache configuration and the exact sequence of calls made to mcp-identity-connector on each inbound request.

Build docs developers (and LLMs) love