Ctrl K
ComunidadGuías…

config.example.env

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Crux Daemon — Configuration
#
# These must be present in the daemon's environment. corecruxd does NOT read a
# .env file — copying this to .env on its own changes nothing, and the daemon
# then exits complaining that CORECRUXD_AUTH_MODE is unset, which looks like a
# config error rather than a file that was never loaded. Export them:
#
#   source config.example.env && ./target/release/corecruxd
#
# or, to load your own edited copy:
#
#   set -a; . ./.env; set +a; ./target/release/corecruxd
#
# Required:
#   CORECRUXD_AUTH_MODE — must be set explicitly (no default).

# ── Required ───────────────────────────────────────────────────────

# Authentication mode. No default — daemon refuses to start without this, and
# refuses to start on an unknown/misspelled value (it never silently falls back
# to dev_scopes). Valid values (exact):
#   off         — No auth (local dev only)
#   dev_scopes  — Scopes from client headers, no verification (testing only)
#   jwt_hs256   — HS256 JWT verification (small deployments)
#   jwt_jwks    — JWKS/OIDC JWT verification (production)
CORECRUXD_AUTH_MODE=off
# Route contracts are enforced in shipped configurations. Unset derives
# enforce whenever auth is enabled or the listener is non-loopback; use
# `shadow` only as an explicit migration diagnostic.
CORECRUXD_ROUTE_AUTH=enforce

# HS256 JWT mode requires at least 32 bytes of secret material. Prefer JWKS/OIDC
# for production; use HS256 only for small controlled deployments.
# CORECRUXD_JWT_HS256_SECRET=
# CORECRUXD_ALLOW_WEAK_HS256_SECRET=false

# HTTP fact-backed surfaces derive their storage tenant from verified JWT
# tenant claims by default. On tenant-implicit routes, multi-tenant/wildcard
# JWTs must select one with X-Corecrux-Tenant-Id; an explicit route/body tenant
# is also a selector and must agree with the header when both are present.
# Invalid values abort startup. `off` is an explicit legacy migration override
# that shares the `default` tenant; `shadow` logs would-change decisions while
# retaining that legacy behaviour.
# This does not tenant-enable MCP or unrelated entity/session/control stores.
# CORECRUXD_TENANT_WRITE_STAMP=on

# ── Storage ────────────────────────────────────────────────────────

# Data directory for segments, indexes, and control state.
CORECRUXD_DATA_DIR=./data

# Build .ccxi companion indexes at seal time for BM25 retrieval.
# Set to 1 if you plan to use text-search queries.
CORECRUXD_BUILD_CCXI=1

# Local CPU BM25 text search is enabled by default. Set the flag to 0 or false
# to hide its HTTP route with a 404 response.
# CORECRUXD_QUERY_TEXT_SEARCH=0

# Dataplane graph expansion and time-range queries remain opt-in.
# CORECRUXD_QUERY_GRAPH_EXPAND=1
# CORECRUXD_QUERY_TIME_RANGE=1

# ── Governance-tier local primitives (default off) ───────────────

# Queryable incident reconstruction cases and certified case exports.
# CORECRUXD_FEATURE_INCIDENTS=false

# Legal-hold placement/release and retention/forget/erasure enforcement.
# CORECRUXD_FEATURE_LEGAL_HOLD=false

# Signed audit-bundle export. When no explicit signing key is supplied, the
# daemon generates one once at CORECRUXD_DATA_DIR/audit-export-signing.key,
# stores it mode 0600, and reuses it for a stable, pinnable issuer identity.
# CORECRUXD_FEATURE_AUDIT_EXPORT=false
# CORECRUXD_AUDIT_EXPORT_SIGNING_KEY_B64=
# CORECRUXD_AUDIT_EXPORT_KEY_ID=

# ── Buyer-Fit Evaluation Capabilities ─────────────────────────────

# examples/eval-profiles/buyer-fit-m0.env sets these for the buyer-fit eval.

# Multi-agent coordination plane for /v1/coord/*: presence, the work board,
# signed handoffs, and leases. Default: ON; explicit 0 disables it.
# CORECRUXD_COORD=true

# Presence liveness TTL in seconds. Default: 900; clamped to 60..=86400.
# CORECRUXD_COORD_PRESENCE_TTL_SECS=900

# Periodic consolidation review scheduler. It only detects and surfaces
# candidates; it never auto-resolves, supersedes, or deletes. Default: OFF.
# CORECRUXD_CONSOLIDATION_SCHEDULER=false

# Review interval in seconds. Default: 3600; clamped to 60..=86400.
# CORECRUXD_CONSOLIDATION_SCHEDULER_INTERVAL_SECS=3600

# Provider-neutral context bundle at /v1/context. Default: OFF; the route
# returns 404 while disabled.
# CORECRUXD_CONTEXT_SURFACE=false

# Gated auto-capture at /v1/memory/* (extract review-only candidates + review
# them). Default: OFF; the routes return 404 while disabled. Auto-extracted
# facts are born-private candidates and only reach recall via an explicit
# promotion; unscored candidates can never be auto-promoted (fail-closed).
# CORECRUXD_AUTO_CAPTURE=false

# Sealed local folder/file ingest at /v1/local/ingest. Default: ON; explicit
# 0 or false disables it and makes the route return 404.
# CORECRUXD_LOCAL_INGEST=true

# Live work-board status feed at /v1/status-feed. Default: OFF.
# CORECRUXD_FEATURE_STATUS_FEED=false

# Signed, replayable activity log at /v1/activity. Default: OFF.
# CORECRUXD_FEATURE_ACTIVITY_LOG=false

# Activity retention horizon in seconds. Default: 31536000 (365 days).
# CORECRUXD_FEATURE_ACTIVITY_LOG_TTL_SECS=31536000

# Co-sign each appended turn when a signer is available. Default: OFF.
# CORECRUXD_FEATURE_ACTIVITY_SIGN=false

# ── Provenance Marking Gateway (BYOK beta) ─────────────────────────

# Default-off /v1/provenance sign, verify, and verify-record routes.
# Requests require provenance:write (or admin:write) plus an explicit tenant
# selector authorized by the JWT tenant_id/tenants claim. Hosted JWTs must also
# carry a stable sub or passport_id: all three operations share a tenant-scoped
# 120-request/min principal budget, so token refresh cannot reset or multiply
# the allowance. The daemon-wide effective-IP limiter remains the outer layer;
# hosted proxies must configure CORECRUXD_TRUSTED_PROXY_CIDRS correctly.
# CORECRUXD_FEATURE_PROVENANCE_API=false

# The daemon does not terminate TLS. When HTTP binds beyond loopback, the
# provenance routes mount only with jwt_hs256/jwt_jwks AND this explicit
# assertion that an upstream proxy provides authenticated TLS termination.
# CORECRUXD_PROVENANCE_TLS_TERMINATED=false

# Optional comma-separated exact leaf-certificate SHA-256 pins for the BYOK
# beta. Accepts 64-hex, sha256:<hex>, or colon-delimited fingerprints; maximum
# 1,024 entries. A pin establishes operator-selected leaf identity only when
# the cert is currently valid and the envelope verifies. It does NOT claim
# CA-chain validation. Malformed configuration keeps the routes unmounted.
# CORECRUXD_PROVENANCE_TRUSTED_LEAF_SHA256=

# Optional comma-separated SHA-256 pins over exact DER self-signed root
# certificates (same accepted formats as the leaf list; maximum 64 entries).
# Unset keeps the CA-chain trust mode OFF. When set, an es256 envelope whose
# presented x5chain cryptographically validates to a pinned root — per-link
# signatures, current validity, BasicConstraints/KeyUsage/EKU leaf + CA
# profiles, path length, fail-closed unsupported critical extensions —
# reports chain_validated=true and, with valid envelope integrity,
# identity_trusted=true (trust_status "trusted_root_chain"). Revocation and
# public C2PA trust-list membership are NOT evaluated. Malformed
# configuration keeps the routes unmounted.
# CORECRUXD_PROVENANCE_TRUSTED_ROOT_SHA256=

# Optional automatic retention window for verification records. Unset means
# no automatic deletion. Valid range: 1..=3650 days. Expired records are
# removed by an authenticated verify-record call at most once per tenant per
# hour, under the tenant's process + cross-process store lock; active legal
# holds are preserved and a count-only receipt covers every deletion attempt.
# Automatic deletion currently fails closed on non-Linux platforms.
# CORECRUXD_PROVENANCE_RETENTION_DAYS=

# Optional bounded JSON object mapping historical daemon passport fingerprints
# to their 32-byte Ed25519 public-key hex. Required after an intentional
# passport-key rotation if older verification records remain; malformed or
# fingerprint-mismatched entries fail retention closed. Maximum 64 keys.
# CORECRUXD_PROVENANCE_RECORD_SIGNER_KEYRING_JSON={}

# Independently default-off scheduler for records belonging to tenants that
# make no new verify-record calls. Enabling it also requires a valid retention
# window above. The Linux-only scheduler skips its boot tick, validates signed
# records and hash-bound tenant directories before deletion, and processes a
# byte-, time-, and tenant-bounded batch.
# CORECRUXD_PROVENANCE_RETENTION_SCHEDULER=false
# CORECRUXD_PROVENANCE_RETENTION_INTERVAL_SECS=3600
# CORECRUXD_PROVENANCE_RETENTION_MAX_TENANTS_PER_PASS=100

# ── Credit Meter / Comped Wallets ─────────────────────────────────

# Default-off credit-burn test rail for seeded comped wallets.
# Enables POST /v1/credits/spend and spend stamping for successful,
# RCX-verified POST /v1/gpu1/rerank calls. Rerank quotes ride at
# options.credit_quote and cost 3 credits. This does not mint fiat credits,
# call Paddle, or enable production billing.
# CORECRUXD_CREDIT_METER=false

# ── Network ────────────────────────────────────────────────────────

# HTTP API port (also serves /healthz, /readyz, /metrics).
CORECRUXD_HTTP_PORT=14800

# gRPC port for data plane operations (append, replay, export).
# CORECRUXD_GRPC_PORT=4007

# Built-in MCP server port (JSON-RPC over Streamable HTTP).
# CORECRUXD_MCP_PORT=14801

# Bind address. Default: 127.0.0.1 (loopback only).
# Set to 0.0.0.0 for network access — requires jwt_hs256 or jwt_jwks auth mode.
# CORECRUXD_HTTP_HOST=127.0.0.1

# MCP bind address. Default: 127.0.0.1 (loopback only).
# If you bind MCP to a non-loopback address, configure CRUX_AGENT_TOKEN or
# CRUX_AGENT_TOKENS unless you intentionally opt into insecure dev binds.
# CORECRUXD_MCP_HOST=127.0.0.1

# MCP agent bearer tokens (enables MCP auth). Token policy: 32..=256 bytes,
# charset [A-Za-z0-9._~-].
#   CRUX_AGENT_TOKEN=<token>                       (single agent named "default")
#   CRUX_AGENT_TOKENS=alice:<token>,bob:<token>    (multiple named agents)
# Fail-closed: if either var is SET but any token is invalid, the daemon refuses
# to start (a typo must never silently downgrade enforced MCP auth to no-auth).
# CRUX_MCP_ALLOW_EMPTY_AGENT_REGISTRY=1 overrides this for local dev/tests ONLY,
# booting with MCP auth disabled — never set it in production.
# CRUX_MCP_ALLOW_EMPTY_AGENT_REGISTRY=1

# Disable the built-in MCP server entirely.
# CORECRUXD_MCP_ENABLED=true

# Minimal public probes: strip routing (node id, shard map), valve state, and
# readiness check detail from the unauthenticated /healthz and /readyz responses.
# Use when those probes are reachable beyond loopback/internal networks. Full
# diagnostics remain available to admin:read callers. Default: off (full detail).
# CORECRUXD_PUBLIC_PROBES_MINIMAL=1

# ── Logging ────────────────────────────────────────────────────────

# Log format: text (human-readable) or json (structured).
CORECRUX_LOG_FORMAT=text

# Log level: trace, debug, info, warn, error.
# CORECRUXD_LOG_LEVEL=info

# Log/ops-fact secret redaction (ExecPlan crux-log-redaction-2026-06-11).
# Scrubs secret-shaped values (JWT eyJ…, sk-…, ghp_…, AKIA…, PEM private-key
# blocks) and denylisted key=value shapes (secret/token/password/api_key/…)
# at the sink boundary — stderr/JSON logs, ops facts, MCP error echoes —
# replacing them with [REDACTED:<rule>#<hash8>] markers. Telemetry field
# names such as token_budget / auth_mode are allowlisted and never touched.
# Modes:
#   off    — no scanning
#   audit  — scan + count rule hits in corecrux_log_redactions_total{rule},
#            output unchanged (DEFAULT; unknown values also fall back here)
#   on     — scan, count, and redact
# Note: the corecrux_log_redactions_total metric family only appears on
# /metrics after the first rule hit (empty families are skipped by the
# Prometheus text encoder) — absence means zero hits, not "not wired".
# CORECRUXD_REDACT=audit

# Extra site-specific value patterns: ';;'-separated id=regex entries, each
# applied alongside the built-in rules as rule id `xtra.<id>`. Invalid
# regexes are logged and skipped (built-ins are never disabled).
#   CORECRUXD_REDACT_EXTRA_PATTERNS='myco=MYCO-[0-9]{6};;legacy=LK_[a-f0-9]{32}'
# CORECRUXD_REDACT_EXTRA_PATTERNS=

# ── Receipt Witness / TSA Preflight ────────────────────────────────
#
# Default-off live witness/TSA settings. Before enabling in production, run:
#   corecruxctl receipts witness-smoke --witness-enabled --witness-provider rekor \
#     --rekor-url "$CORECRUXD_REKOR_URL" \
#     --tsa-enabled --tsa-url "$CORECRUXD_TSA_URL" \
#     --tsa-root-cert "$CORECRUXD_TSA_ROOT_CERT_PATH"
# The daemon also exposes the same local-only check at /v1/witness/smoke.
# These checks do not submit to Rekor or a TSA.
# CORECRUXD_WITNESS_ENABLED=false
# CORECRUXD_WITNESS_PROVIDER=rekor
# CORECRUXD_WITNESS_TIMEOUT_MS=5000
# CORECRUXD_REKOR_URL=https://rekor.sigstore.dev
# CORECRUXD_REKOR_PUBLIC_KEY_PATH=/etc/corecrux/rekor.pub
# CORECRUXD_TSA_ENABLED=false
# CORECRUXD_TSA_URL=https://tsa.example
# CORECRUXD_TSA_ROOT_CERT_PATH=/etc/corecrux/tsa-root.pem
# CORECRUXD_TSA_POLICY_OID=1.2.3.4

# ── Agent / MCP ────────────────────────────────────────────────────

# Agent authentication token. Agents include this as Bearer token. Tokens must
# be 32..=256 ASCII chars from [A-Za-z0-9._~-].
# Generate with: openssl rand -hex 32
# CRUX_AGENT_TOKEN=

# Optional multi-agent token registry:
#   alice:<32-byte-token>,bob:<32-byte-token>
# CRUX_AGENT_TOKENS=

# MCP Streamable HTTP SSE session caps. Defaults: 1024 open streams globally
# and 64 per authenticated agent, or per client IP when no agent is present.
# Set either value to 0 only for emergency rollback/no-cap local debugging.
# CRUX_MCP_SSE_MAX_SESSIONS=1024
# CRUX_MCP_SSE_MAX_SESSIONS_PER_OWNER=64

# Stable secret for MCP handoff package authentication.
# If unset, handoff verification keys are process-local and rotate on restart.
# CRUX_MCP_HANDOFF_SECRET=

# ── Unified login auth rails (crux login) ──────────────────────────
#
# Opt-in daemon-side rails for `corecruxctl login`. Both default OFF, so
# existing deployments are unaffected. Issuance (tailscale + device) mints
# short-lived (≤5 min) HS256 JWTs and therefore requires the daemon to run in
# jwt_hs256 mode (CORECRUXD_AUTH_MODE=jwt_hs256 + CORECRUXD_JWT_HS256_SECRET);
# otherwise the token endpoints return 503.

# ── Work-gate approver policy ───────────────────────────────────────────────
# How many DISTINCT PASSPORTS must take part in resolving a gated work
# transition. Default 2 — the requesting passport cannot resolve its own gate.
#
#   2  the requester may not approve their own gate (default)
#   1  single-party approval permitted
#
# Set 1 when there is genuinely one human in the loop. A hard ban does not
# create separation of duties on a one-person deployment — it creates a second
# passport minted solely to approve one's own work, which passes the check while
# recording `distinct_passports` for what is really one person. That is a worse
# audit trail than admitting single-party approval.
#
# Either way the SIGNED approval receipt records what actually happened:
#   approvers=<policy> parties=<1|2> sep=<distinct_passports|none:self_approved>
#
# Note `distinct_passports` means exactly that. The daemon verifies two
# passports differ; it cannot establish they belong to two people, and the
# receipt never claims otherwise.
#
# Anything unset, malformed, or out of range resolves to 2 — a typo must never
# silently relax a human-oversight boundary.
# CORECRUXD_WORK_GATE_APPROVERS=2

# Rail 2 — Trusted-proxy identity. An authenticating reverse proxy injects a
# verified per-human identity header; the daemon maps it to a principal. When
# enabled, GET /v1/auth/whoami echoes the trusted identity and
# POST /v1/auth/tailscale/token mints a scoped JWT for allowlisted identities.
# Disabled ⇒ 404.
# CORECRUXD_TS_IDENTITY_ENABLED=false
#
# Which header carries the identity. Defaults to the `tailscale serve` preset,
# so leaving this unset preserves existing behaviour. Presets:
#   tailscale serve ......... tailscale-user-login   (default)
#   oauth2-proxy ............ x-forwarded-email  |  x-auth-request-email
#   Cloudflare Access ....... cf-access-authenticated-user-email
#   Authelia ................ remote-email
#   Authentik ............... x-authentik-email
#
# SECURITY: your proxy MUST strip-then-set this header on every forwarded
# request. A trusted CIDR proves the proxy SENT the request, not that it
# AUTHORED the header — a proxy that forwards a client-supplied value hands any
# client a free identity. tailscale serve and Cloudflare Access overwrite by
# construction; oauth2-proxy and Authelia depend on configuration. If you cannot
# guarantee it, use rail 3 (device grant) instead, which takes identity from an
# approver rather than a header.
# CORECRUXD_IDENTITY_HEADER=tailscale-user-login
#
# Allowlist mapping verified logins → principal. Format (comma-separated):
#   login=tenant:scopeA|scopeB[#passport_id]
# e.g. alice@example.com=acme:facts:write|query:read#p_alice,ci@example.com=acme:query:read
# The tenant + scopes here are authoritative; the client cannot influence them (T.1).
# The `#passport_id` suffix is what makes a human's decisions attributable: it
# binds the login to a canonical passport, so tokens minted for them — and
# console Approve/Reject clicks forwarded by a trusted proxy on a shared bridge
# JWT — resolve work gates and passport-mint requests AS that passport. Without
# it the login is known but unbound and every human-decision route refuses.
# CORECRUXD_TS_IDENTITY_ALLOWLIST=
#
# Extra CIDRs whose peer may present identity headers. Loopback is always trusted
# (the proxy is same-host); set this only if the proxy peer is non-loopback.
# CORECRUXD_TS_TRUSTED_PROXY_CIDRS=

# Rail 3 — Device authorization grant (RFC 8628), the browser/"Claude-style"
# login for callers with no host/env access. When enabled:
#   POST /v1/auth/device/start  → device_code + user_code + verification_uri
#   /activate                   → operator approval page (console admin: admin:write)
#   POST /v1/auth/device/token  → poll → access_token + refresh_token once approved
#   POST /v1/auth/device/refresh / revoke → rotate / revoke the refresh credential
# Disabled ⇒ 404.
# CORECRUXD_DEVICE_GRANT_ENABLED=false

# Unify HTTP + MCP on one credential. When the daemon runs in a JWT mode,
# also accept a registered MCP agent token (CRUX_AGENT_TOKENS) on the HTTP API,
# so a single `corecruxctl login --token <agent-token>` unlocks both :14800 and
# :14801. Default off (HTTP stays JWT-only). Agent tokens carry no claims, so
# every accepted agent token maps to the scope set + tenant below.
# CORECRUXD_HTTP_ACCEPT_AGENT_TOKENS=false
# Scopes granted to an HTTP-accepted agent token (space/comma separated).
# Default: admin:read admin:write facts:write query:read sessions:read sessions:write
# CORECRUXD_AGENT_TOKEN_HTTP_SCOPES=
# Tenant binding for HTTP-accepted agent tokens. `*` = all tenants. Default: *
# CORECRUXD_AGENT_TOKEN_HTTP_TENANT=*

# ── Git Update Checks ──────────────────────────────────────────────

# Compare this checkout against a tracked git branch and expose the cached
# result through /v1/version and the MCP update_status tool.
# Disable only if the node runs outside a git checkout or you do not want
# any background version checks.
# CORECRUXD_UPDATE_CHECK_ENABLED=true

# Tracking branch to compare against.
# CORECRUXD_UPDATE_CHECK_REMOTE=origin
# CORECRUXD_UPDATE_CHECK_REF=main

# Refresh cadence in seconds. Default: 3600.
# CORECRUXD_UPDATE_CHECK_INTERVAL_SECS=3600

# Optional explicit repo root when the service manager starts corecruxd from a
# different working directory.
# CORECRUXD_UPDATE_CHECK_REPO_DIR=/srv/corecrux

# ── Ingress Hardening ──────────────────────────────────────────────
#
# Transport-level protection for the HTTP planes (:14800 API, :14801 MCP).
# All limits accept 0 = disabled/unbounded for emergency rollback without
# a redeploy.

# Maximum accepted HTTP request body in bytes for ordinary routes. Oversized
# requests get a 413 application/problem+json response. Default: 16777216
# (16 MB). Bulk/import routes keep explicit 64 MB route caps.
# CORECRUXD_MAX_REQUEST_BODY_BYTES=16777216

# Hard cap (seconds) on the graceful-shutdown connection drain. After the
# cap, remaining connections are force-closed (logged as a warning).
# Default 30 matches the router-wide request timeout. 0 = drain forever.
# CORECRUXD_SHUTDOWN_DRAIN_SECS=30

# Maximum concurrently-admitted HTTP requests per listener. Excess requests
# are load-shed with a 503 problem+json + Retry-After before any body byte
# is read. Inflight count exported as the corecrux_http_inflight gauge.
# Default: 1024. 0 = no cap.
# CORECRUXD_MAX_INFLIGHT=1024

# Sustained per-client-IP request rate (requests/second). Passport headers
# are validated but are not trusted as pre-auth rate-limit keys. Excess
# requests get a 429 application/problem+json + Retry-After; rejections are
# counted in corecrux_http_rate_limited_total{key_kind}. Default: 300.
# 0 = rate limiting disabled.
# CORECRUXD_RATE_LIMIT_RPS=300

# Per-key burst capacity (token-bucket depth). Values below the sustained
# rate are clamped up to it. Default: 600.
# CORECRUXD_RATE_LIMIT_BURST=600

# Comma-separated CIDRs whose effective client IPs bypass rate limiting
# entirely. Default: loopback only — keeps direct console SPA and local agents
# unthrottled. Forwarded headers from untrusted peers suppress this exemption,
# so an unconfigured same-host reverse proxy gets one shared daemon bucket
# instead of an unlimited loopback bypass. Invalid entries are logged and
# skipped. Empty value = no exemptions.
# CORECRUXD_RATE_LIMIT_EXEMPT_CIDRS=127.0.0.0/8,::1/128

# Comma-separated CIDRs for trusted reverse proxy peers. Only these peers may
# supply Forwarded / X-Forwarded-For for daemon-side client-IP rate limiting.
# If omitted, forwarded headers are ignored. For same-host Caddy/nginx/Envoy,
# set this to 127.0.0.1/32,::1/128 only when the proxy strips inbound
# Forwarded/X-Forwarded-For and rewrites them from the real client address.
# CORECRUXD_TRUSTED_PROXY_CIDRS=

# gRPC plane (:4007) HTTP/2 keep-alive ping interval in seconds. Dead peers
# are reaped instead of holding connections open indefinitely. Default: 30.
# 0 = keep-alive pings disabled.
# CORECRUXD_GRPC_KEEPALIVE_INTERVAL_SECS=30

# How long to wait for a keep-alive ping ack before closing the gRPC
# connection, in seconds. Only meaningful when the interval is non-zero.
# Default: 10.
# CORECRUXD_GRPC_KEEPALIVE_TIMEOUT_SECS=10

# Maximum concurrent HTTP/2 streams per gRPC connection. Transport-level
# protection only — the per-tenant token-bucket throttle remains the
# fairness layer. Default: 1024. 0 = unbounded.
# CORECRUXD_GRPC_MAX_CONCURRENT_STREAMS=1024

# ── Optional Remote Sync / Hosted Platform ────────────────────────

# Crux Daemon works fully in local-only mode by default.
# Set the variables below only if you want this node to sync facts with an
# upstream CoreCrux deployment.

# Enable the background pull/push sync loop.
# CORECRUXD_SYNC_ENABLED=false

# Remote CoreCrux HTTP base URL, for example:
# CORECRUXD_SYNC_REMOTE_URL=https://corecrux.example.com

# Bearer token for the remote sync target.
# CORECRUXD_SYNC_API_KEY=

# Background sync interval in seconds. Default: 300.
# CORECRUXD_SYNC_INTERVAL_SECS=300

# Require every sync server request to present an issuer-signed Ed25519 peer
# handshake. Default: false. When enabled, facts/admin scopes cannot bypass
# the handshake. The nonce challenge remains public.
# CORECRUXD_SYNC_MUTUAL_AUTH=false

# Ed25519 VaultCrux/issuer trust-root public key used to verify peer capability
# tokens: exactly 64 hex characters (32 bytes, no 0x prefix). An enabled mutual-
# auth deployment with this unset or invalid rejects sync requests fail-closed.
# CORECRUXD_SYNC_PEER_TRUST_ROOT=

# Peer flow: POST /v1/sync/handshake/nonce, then present these headers on a
# tenant sync request:
#   x-crux-peer-token  = RFC 4648 standard-base64 of RcxCapabilityToken JSON
#   x-crux-peer-pubkey = hex Ed25519 peer public key (32 bytes)
#   x-crux-peer-nonce  = hex nonce returned by the challenge endpoint (32 bytes)
#   x-crux-peer-sig    = hex Ed25519 signature over the M2a signing message (64 bytes)

# ── Enterprise Customer-Hosted Trust Root ─────────────────────────

# Enable only for customer-hosted Enterprise deployments. When enabled,
# corecruxd validates the trust-root contract at startup before customer
# hosted backends can be used.
# CORECRUXD_ENTERPRISE_ENABLED=false
# CORECRUXD_ENTERPRISE_CUSTOMER_ID=customer-a
# CORECRUXD_ENTERPRISE_BACKEND_ID=customer:cluster-a
# CORECRUXD_ENTERPRISE_TRUST_ROOT_KID=customer-root-a
# CORECRUXD_ENTERPRISE_TRUSTED_ISSUER_KIDS=customer-issuer-a,customer-issuer-b
# CORECRUXD_ENTERPRISE_AIRGAP=true
# CORECRUXD_ENTERPRISE_ALLOW_VAULTCRUX_CROSS_SIGN=false

# ── Embeddings (optional) ──────────────────────────────────────────
#
# Point Crux at any OpenAI-compatible embedding endpoint to enable dense
# vector retrieval on facts. Ollama, vLLM, llama.cpp, TEI, and LiteLLM
# all expose a compatible API.
#
# When set, facts are embedded at store time and queries rank results by
# cosine similarity blended with confidence. When unset, Crux uses
# keyword matching only (no external dependencies).

# Embedding service base URL. Leave unset to disable embeddings.
# CORECRUXD_EMBEDDING_URL=http://localhost:11434

# Embedding console probe blocks private, loopback, link-local, metadata, and
# DNS-rebinding targets unless the target matches CORECRUXD_EMBEDDING_URL.
# Set only for local setup/debugging when probing arbitrary local endpoints.
# CORECRUXD_EMBEDDING_PROBE_ALLOW_LOCAL=false

# Model name to request from the embedding service.
# CORECRUXD_EMBEDDING_MODEL=nomic-embed-text

# Offline default dense embedder (buyer-fit M3.2). When no CORECRUXD_EMBEDDING_URL
# is set, facts and locally-ingested prose are embedded with the zero-dependency
# pure-Rust LocalHashEmbedder, so dense recall works offline with no external
# service. Set to 0/false to keep the fact lane keyword-only.
# CORECRUXD_LOCAL_EMBEDDER=true

# Optional real local embedding model (buyer-fit M3.4). Set to `fastembed` to use
# the ONNX all-MiniLM-L6-v2 model (downloaded on first use into the data dir).
# Requires the daemon built with `--features dense-embed-model`; otherwise the
# LocalHashEmbedder is used. Only consulted when CORECRUXD_EMBEDDING_URL is unset.
# CORECRUXD_DENSE_MODEL=fastembed

# Memory budget, in bytes, for the parsed `.ccxe` dense companions the query
# path keeps hot. This is a memory bound, NOT a recall cap: an evicted companion
# is re-read from disk on the next query, so the candidate set and the scores are
# identical either way — the dense lane stays uncapped and exact. Default 512 MiB.
# Raise it on a host with memory to spare (fewer re-reads); lower it on a small
# one. `0` disables the bound entirely, which is what let one dense query over a
# ~900-segment corpus OOM-kill a 5.5 GiB daemon (#740).
# CORECRUXD_DENSE_CACHE_BUDGET_BYTES=536870912

# Store-time semantic near-duplicate detection (buyer-fit M3.5). When enabled and
# a dense embedder is configured, a newly stored fact whose vector is highly
# similar to an existing distinct fact is FLAGGED as a review candidate (logged +
# queryable) — never dropped. Off by default.
# CORECRUXD_SEMANTIC_DEDUP=false
# Cosine threshold for the flag (default 0.95).
# CORECRUXD_SEMANTIC_DEDUP_THRESHOLD=0.95

# ── Pack lifecycle (extensions) ────────────────────────────────────

# Staged activation (buyer-fit M5). When enabled, a newly installed pack lands
# `staged` instead of live: it can be invoked and its writes are returned for
# inspection, but nothing reaches canonical memory until an operator activates
# it via POST /v1/extensions/{id}/lifecycle. Off by default — installs stay
# immediately live, and packs installed before this flag existed are unaffected.
# Quarantine and activation work regardless of this flag; it only picks the
# state a fresh install starts in.
# CORECRUXD_PACK_STAGING=false

# ── CoreCrux operator proxy (optional) ─────────────────────────────
#
# Enables /console lane-weight controls to read and write CoreCrux boost
# overlays through this Crux daemon. Vectors stay in CoreCrux; Crux only
# proxies operator-authenticated admin requests.
#
# On Tailscale deployments, use the CoreCrux daemon's Tailscale HTTPS/HTTP
# base URL here. Leave unset to hide the live lane-weight state behind a
# clear "CoreCrux base URL is not configured" console error.
# CORECRUXD_CORECRUX_BASE_URL=http://corecrux:14800
#
# Optional bearer token and passport id forwarded to CoreCrux when its admin
# API is not running in dev-scopes mode.
# CORECRUXD_CORECRUX_ADMIN_TOKEN=
# CORECRUXD_CORECRUX_PASSPORT_ID=

# ── Debugging ──────────────────────────────────────────────────────

# Include internal topology in error responses (GPU IDs, gRPC addresses).
# CORECRUXD_DEBUG_ERRORS=false

# Default session TTL in seconds. 0 = no expiry.
# CORECRUXD_SESSION_TTL_DEFAULT=0