JamJet

Enterprise Security

Multi-tenant isolation, PII redaction, OAuth delegation, mTLS federation, and data retention policies in JamJet.

Enterprise Security

JamJet's enterprise features are enforced at the Rust runtime layer — not by convention, not by middleware you might forget to add.

Multi-tenant isolation

Partition all storage by tenant ID. Workflow definitions, execution state, event logs, audit trails, and snapshots are scoped per tenant.

# Same workflow, different tenants — fully isolated
jamjet run workflow.yaml \
  --input '{"invoice_id": "INV-001", "amount": 2500}' \
  --tenant acme

jamjet run workflow.yaml \
  --input '{"invoice_id": "INV-042", "amount": 75000}' \
  --tenant globex

The runtime's TenantScopedSqliteBackend wraps every storage query with WHERE tenant_id = ?. The workflow definition table uses a composite primary key (tenant_id, workflow_id, version).


PII redaction

Declare a data_policy in your workflow. The runtime applies it before any state reaches the audit log.

data_policy:
  pii_detectors: [email, ssn, phone, credit_card, ip_address]
  pii_fields: ["$.email", "$.ssn", "$.credit_card"]
  redaction_mode: mask        # or: hash, remove
  retain_prompts: false       # strip prompts from audit log
  retain_outputs: false       # strip model outputs from audit log
  retention_days: 90          # auto-purge after 90 days

Three redaction modes:

ModeBehaviorExample
maskPartial reveal for debugging***-**-6789
hashSHA-256 pseudonymization for analyticsa3f2c91b...e71b
removeFull field deletion(field deleted)

Python SDK equivalent:

@workflow(
    id="customer-onboarding",
    version="0.1.0",
    data_policy={
        "pii_detectors": ["email", "ssn", "phone", "credit_card"],
        "pii_fields": ["$.email", "$.ssn"],
        "redaction_mode": "mask",
        "retain_prompts": False,
        "retain_outputs": False,
        "retention_days": 90,
    },
)
class CustomerOnboarding:
    ...

Data retention

retention_days sets an expires_at timestamp on every audit log entry. The runtime's purge_expired() method runs as a background task, deleting entries past their expiry date.

Additional controls:

  • retain_prompts: false — strips model prompts from audit entries before writing
  • retain_outputs: false — same for model outputs

The audit log retains metadata (node ID, token counts, timestamps) without the content.


OAuth 2.0 delegation

RFC 8693 token exchange. The user's token is exchanged for a narrowly-scoped agent token.

oauth:
  token_endpoint: "${JAMJET_OAUTH_TOKEN_ENDPOINT}"
  grant_type: "urn:ietf:params:oauth:grant-type:token-exchange"
  client_id: "${JAMJET_OAUTH_CLIENT_ID}"
  client_secret: "${JAMJET_OAUTH_CLIENT_SECRET}"
  requested_scopes: ["expenses:read", "expenses:write"]

Scope narrowing

The agent's effective scopes are the intersection of what it requests and what the user has. If the intersection is empty, the runtime returns OAuthError::ScopeNarrowingFailed.

Per-step scoping

Different nodes can declare different scope requirements:

nodes:
  authenticate:
    oauth_scopes:
      required_scopes: ["expenses:read"]

  submit-expense:
    oauth_scopes:
      required_scopes: ["expenses:read", "expenses:write"]

The runtime resolves scopes before every node executes — not once at workflow start.

Token validity

check_token_validity() runs before every tool and model invocation. Expired or revoked tokens produce clean errors (OAuthError::TokenExpired, OAuthError::TokenRevoked) and escalate to a human.


mTLS and A2A federation

For cross-organization agent communication:

Transport: mutual TLS. Both sides present certificates, both sides verify.

export JAMJET_TLS_CERT=/etc/certs/agent.pem
export JAMJET_TLS_KEY=/etc/certs/agent-key.pem
export JAMJET_TLS_CA_CERT=/etc/certs/ca.pem
export JAMJET_MTLS_REQUIRED=true

Application: capability-scoped Bearer tokens with agent allowlists.

federation:
  require_auth: true
  public_agent_card: true
  tokens:
    - token: "tok-alpha"
      name: "Research Agent"
      agent_id: "agent-alpha"
      scopes: ["read", "write"]
  allowed_agents: ["agent-alpha"]
  method_scopes:
    "tasks/send": ["write"]
    "tasks/get": ["read"]

The federation_auth_layer middleware validates every incoming A2A request. Unauthorized requests get a JSON-RPC error before reaching the handler.


Pluggable secret backends

Chain multiple secret sources with priority ordering:

BackendUse case
Environment variablesLocal dev, CI
File-basedKubernetes secrets, mounted volumes
HashiCorp VaultProduction secret management
AWS Secrets ManagerAWS-native deployments

The runtime resolves secrets at startup by checking backends in priority order.


Examples

Runnable examples for each enterprise feature:

git clone https://github.com/jamjet-labs/examples
cd examples/multi-tenant       # tenant isolation
cd examples/data-governance    # PII redaction + retention
cd examples/oauth-delegation   # OAuth 2.0 + scope narrowing

tip: Read the full deep dives: data governance and PII redaction, OAuth delegation and federation auth.

On this page