# 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:, 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= (single agent named "default") # CRUX_AGENT_TOKENS=alice:,bob: (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:#] 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.`. 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= parties=<1|2> sep= # # 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 ` 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