Secrets
A secret is an opaque, redacted value: you can use it but never read its
plaintext from the language. It is LLM-proof by design — it never appears in print,
logs, error bodies, JSON responses, the blackboard, or an LLM prompt.
env() vs secret()
env(name, default?)→ plain, visible text config (URLs, ports, flags).secret(name, default?)→ an opaque, redacted credential (API keys, tokens, signing secrets).
Both are deny-by-default: declare the capability or the read fails.
-- Doc example (UNIVERSAL — one source, shared by every language).
-- Comments are English on purpose: the code is the same in /en, /es, /pt, ...
-- Doctest gate: `synsema test docs/0.4.x/examples/` must be green to publish.
intent: "doc example: a secret stays redacted everywhere except the socket"
require secret("API_KEY")
print("a secret prints as → " + text(secret("API_KEY", "sk-demo-123"))) -- redacted
test "a secret is redacted in every string surface"
let k be secret("API_KEY", "sk-demo-123")
assert_eq(text(k), "secret(API_KEY)") -- never the real value
assert_eq(type_of(k), "secret")
-- GOTCHA: concatenating text + secret yields a SECRET, and it redacts WHOLE —
-- the "Authorization: " prefix is absorbed, you do NOT get "Authorization: secret(...)".
assert_eq(type_of("Authorization: " + k), "secret")
assert_eq(text("Authorization: " + k), "secret(API_KEY)") -- prefix absorbed (taint)
test "bearer() builds a tainted Authorization value"
let b be bearer(secret("API_KEY", "sk-demo-123"))
assert_eq(type_of(b), "secret") -- still a secret
assert_eq(text(b), "secret(API_KEY)") -- redacted, even as a Bearer value
test "a raw secret goes in ANY header, not just Bearer"
-- materialization to the real value happens ONLY at the socket; here we just show
-- it stays a redacted secret in your program's value space (see /docs/.../secrets).
let headers be {"x-api-key": secret("API_KEY", "sk-demo-123")}
assert_eq(text(headers["x-api-key"]), "secret(API_KEY)")
test "as_secret seals a value that arrives at runtime"
let sealed be as_secret("rk-from-user", "user_key") -- e.g. a tenant's key from a header
assert_eq(text(sealed), "secret(user_key)")
assert_eq(type_of(sealed), "secret")
Credentials go in any header — not just Bearer
A secret placed as a header value is materialized to its real value **only at the
socket, regardless of the header name. So you are not** limited to Authorization:
- Custom header:
{"x-api-key": secret("API_KEY")} - Your own header:
{"x-whatever": secret("API_KEY")} - Bearer (just sugar for
Authorization: Bearer <token>):{"Authorization": bearer(secret("API_KEY"))}
In query params and the body a secret is redacted (fail-closed) — a credential
only survives over the wire inside a header.
as_secret() — seal a value that arrives at runtime
secret("NAME") reads from config. For a value that arrives at runtime and is not in
.env (a tenant's key in a request header, a token from another HTTP call), seal it at
the edge with as_secret(value, label?). It is pure (no require), idempotent on a
secret, and accepts text or bytes.
reveal() — the audited last resort
reveal(secret) returns the plaintext. It requires require reveal("NAME") **scoped to
the secret's name/label**, writes an append-only audit entry for every attempt, and warns
on the bare (unscoped) form. Prefer bearer/hmac_sha256/verify_hmac — they consume the
secret without exposing it.