Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/PaymanAI/sigilum/llms.txt

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

Overview

Gateway proxy endpoints forward signed HTTP requests to configured upstream services after validating:
  1. RFC 9421 signature verification
  2. Nonce replay protection
  3. Approved claim validation
  4. Connection configuration and secrets
Upon successful validation, Gateway injects connector-managed credentials and strips Sigilum signing headers before forwarding to the upstream.

Proxy Request Flow

Generic Proxy Endpoint

connection_id
string
required
Connection identifier configured in Gateway (e.g., slack-proxy, linear-api)
proxy_path
string
required
Upstream path to forward (e.g., chat.postMessage, api/v1/issues)

Required Headers

All proxy requests require Sigilum signature headers:
signature-input
string
required
RFC 9421 Signature-Input headerExample: sig1=("@method" "@path" "@authority" "content-digest" "sigilum-namespace" "sigilum-subject" "sigilum-agent-key" "sigilum-nonce");created=1709550000;keyid="key-abc123";nonce="nonce_xyz789"
signature
string
required
RFC 9421 Signature header with base64-encoded signatureExample: sig1=:MEUCIA...:==
sigilum-namespace
string
required
Sigilum namespace identifier
sigilum-subject
string
required
Stable requester identifier within namespace (user ID, employee ID, or app principal)
sigilum-agent-key
string
required
Base64-encoded public key of signing agent
sigilum-agent-cert
string
required
Agent certificate for signature verification

Signed Component Requirements

The signature-input header must include these components:
  • @method - HTTP method
  • @path - Request path
  • @authority - Host authority
  • content-digest - SHA-256 digest of request body (if body present)
  • sigilum-namespace
  • sigilum-subject
  • sigilum-agent-key
  • sigilum-nonce - Unique nonce for replay protection
Additional parameters:
  • created - Unix timestamp of signature creation
  • keyid - Key identifier
  • nonce - Nonce value (must match sigilum-nonce header)
If the signed component set doesn’t match the required profile, Gateway returns AUTH_SIGNED_COMPONENTS_INVALID (403).

Response

(varies)
any
Gateway forwards the upstream response body transparently
(error)
object
On auth failure, returns error envelope:
  • error (string) - Human-readable error summary
  • code (string) - Error code from taxonomy
  • request_id (string) - Correlation ID
  • timestamp (string) - RFC3339 UTC timestamp
  • docs_url (string) - Remediation reference URL

Example: Slack Message

curl -X POST https://localhost:38100/proxy/slack-proxy/chat.postMessage \
  -H 'Content-Type: application/json' \
  -H 'signature-input: sig1=("@method" "@path" "@authority" "content-digest" "sigilum-namespace" "sigilum-subject" "sigilum-agent-key" "sigilum-nonce");created=1709550000;keyid="key-abc";nonce="nonce_xyz"' \
  -H 'signature: sig1=:MEUCIA...:' \
  -H 'sigilum-namespace: acme-corp' \
  -H 'sigilum-subject: user_alice' \
  -H 'sigilum-agent-key: MFkwEwYHK...' \
  -H 'sigilum-agent-cert: MIIBkTC...' \
  -H 'sigilum-nonce: nonce_xyz' \
  -H 'content-digest: sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:' \
  -d '{
    "channel": "C1234567890",
    "text": "Hello from Gateway!"
  }'
Gateway Processing:
  1. Verifies signature with sigilum-agent-key
  2. Checks nonce_xyz not seen before for acme-corp namespace
  3. Validates (acme-corp, MFkwEwYHK..., slack-proxy) approved claim exists
  4. Resolves slack-proxy connection config and decrypts secret
  5. Strips all sigilum-*, signature*, content-digest headers
  6. Injects Authorization: Bearer xoxb-... header
  7. Forwards to https://slack.com/api/chat.postMessage
Success Response (200 OK):
{
  "ok": true,
  "channel": "C1234567890",
  "ts": "1709550123.000000",
  "message": {
    "text": "Hello from Gateway!",
    "username": "bot",
    "bot_id": "B1234567890",
    "type": "message",
    "subtype": "bot_message",
    "ts": "1709550123.000000"
  }
}

Example: Auth Failure

{
  "error": "replay detected",
  "code": "AUTH_REPLAY_DETECTED",
  "request_id": "req_9k3j2h1",
  "timestamp": "2026-03-04T10:30:15Z",
  "docs_url": "https://docs.sigilum.id/gateway-errors#AUTH_REPLAY_DETECTED"
}

Slack Alias Endpoint

slack_path
string
required
Slack API path (e.g., chat.postMessage, users.list)
The /slack/* route is hardcoded to connection ID slack-proxy. This alias cannot be changed via environment variables.

Example: Slack Alias

curl -X POST https://localhost:38100/slack/chat.postMessage \
  -H 'Content-Type: application/json' \
  -H 'signature-input: ...' \
  -H 'signature: ...' \
  -H 'sigilum-namespace: acme-corp' \
  -H 'sigilum-subject: user_alice' \
  # ... (same signature headers as generic proxy)
  -d '{"channel": "C123", "text": "Hello"}'
This is equivalent to:
curl -X POST https://localhost:38100/proxy/slack-proxy/chat.postMessage ...

Auth Modes

Gateway supports three credential injection modes when forwarding to upstream:

Bearer Token (auth_mode: "bearer")

Injects Authorization header with Bearer token:
Authorization: Bearer <secret>
Connection Configuration:
{
  "auth_mode": "bearer",
  "auth_header_name": "Authorization",
  "auth_prefix": "Bearer ",
  "auth_secret_key": "bot_token",
  "secrets": {
    "bot_token": "xoxb-1234567890-abcdefghij"
  }
}

Header Key (auth_mode: "header_key")

Injects custom header with secret:
X-API-Key: <secret>
Connection Configuration:
{
  "auth_mode": "header_key",
  "auth_header_name": "X-API-Key",
  "auth_prefix": "",
  "auth_secret_key": "api_key",
  "secrets": {
    "api_key": "sk_live_abc123xyz789"
  }
}

Query Parameter (auth_mode: "query_param")

Appends secret to query string:
https://api.example.com/endpoint?api_key=<secret>
Connection Configuration:
{
  "auth_mode": "query_param",
  "auth_header_name": "api_key",
  "auth_prefix": "",
  "auth_secret_key": "api_key",
  "secrets": {
    "api_key": "secret_xyz789"
  }
}
Query parameter mode exposes credentials in URLs. Only use for services that require this pattern.

Shared Credential Variables

Gateway supports reusable credential variables referenced across multiple connections: Define Shared Variable:
curl -X POST http://localhost:38100/api/admin/credential-variables \
  -H 'Content-Type: application/json' \
  -H 'sigilum-subject: user_alice' \
  -d '{
    "key": "OPENAI_API_KEY",
    "value": "sk-proj-abc123xyz789"
  }'
Reference in Connection:
{
  "id": "openai-api",
  "name": "OpenAI API",
  "protocol": "http",
  "base_url": "https://api.openai.com",
  "auth_mode": "bearer",
  "auth_header_name": "Authorization",
  "auth_prefix": "Bearer ",
  "auth_secret_key": "api_key",
  "secrets": {
    "api_key": "{{OPENAI_API_KEY}}"
  }
}
Gateway resolves {{OPENAI_API_KEY}} at runtime from shared variables store.
Shared variables include created_by_subject for audit traceability. The sigilum-subject header takes precedence over request body when creating variables.

Unsigned Proxy Mode (Development)

For local development, Gateway can bypass signature verification for specific connections: Configuration:
GATEWAY_ALLOW_UNSIGNED_PROXY=true
GATEWAY_ALLOW_UNSIGNED_CONNECTIONS=slack-proxy,linear-api
Never enable unsigned proxy mode in production. This bypasses all Sigilum auth checks and should only be used for local testing.

Error Scenarios

Missing Required Headers

Request:
curl -X POST https://localhost:38100/proxy/slack-proxy/chat.postMessage \
  -H 'Content-Type: application/json' \
  -d '{"channel": "C123", "text": "Hello"}'
# Missing signature headers
Response (403 Forbidden):
{
  "error": "invalid or duplicate signed headers",
  "code": "AUTH_HEADERS_INVALID",
  "request_id": "req_abc123",
  "timestamp": "2026-03-04T10:30:00Z"
}

Invalid Signature

Response (403 Forbidden):
{
  "error": "signature verification failed",
  "code": "AUTH_SIGNATURE_INVALID",
  "request_id": "req_def456",
  "timestamp": "2026-03-04T10:31:00Z"
}

Claim Not Approved

Response (403 Forbidden):
{
  "error": "caller is not currently approved for the requested service",
  "code": "AUTH_CLAIM_REQUIRED",
  "request_id": "req_ghi789",
  "timestamp": "2026-03-04T10:32:00Z"
}

Connection Not Found

Response (404 Not Found):
{
  "error": "connection not found",
  "code": "CONNECTION_NOT_FOUND",
  "request_id": "req_jkl012",
  "timestamp": "2026-03-04T10:33:00Z"
}

Upstream Timeout

Response (504 Gateway Timeout):
{
  "error": "upstream request timeout",
  "code": "UPSTREAM_TIMEOUT",
  "request_id": "req_mno345",
  "timestamp": "2026-03-04T10:34:00Z"
}

Rotation Enforcement

Gateway can enforce credential rotation policies:
GATEWAY_ROTATION_ENFORCEMENT=block  # off | warn | block
GATEWAY_ROTATION_GRACE_DAYS=90
In block mode, overdue connections return: Response (403 Forbidden):
{
  "error": "credential rotation required",
  "code": "ROTATION_REQUIRED",
  "request_id": "req_pqr678",
  "timestamp": "2026-03-04T10:35:00Z"
}

Decision Logging

When GATEWAY_LOG_PROXY_REQUESTS=true, Gateway emits structured JSON decision logs:
{
  "level": "info",
  "type": "gateway_decision",
  "decision_type": "proxy_auth_denied",
  "request_id": "req_abc123",
  "connection": "[redacted]",
  "namespace": "[hashed]",
  "subject": "[hashed]",
  "remote_ip": "192.168.1.0",
  "stage": "replay_detection",
  "decision": "deny",
  "reason_code": "AUTH_REPLAY_DETECTED",
  "timestamp": "2026-03-04T10:30:15Z"
}
Gateway automatically redacts secret-bearing fields, hashes identity fields, and masks client IPs before logging.

Next Steps

MCP Runtime

Explore MCP tool discovery and execution

Admin Endpoints

Manage connections and credentials