Files
pig/.env.example
T
karti c821b2ca07
CI / verify (push) Successful in 2m55s
Authenticate against any OIDC provider, for on-premises installs
The seam existed with only a Supabase implementation, so an on-prem deployment
had no way to authenticate. A customer running PIG inside their own network
already has Okta, Entra, Keycloak, Auth0 or Google Workspace; asking them to
stand up a second identity system is a serious adoption tax and in a regulated
environment usually refused outright.

Setting PIG_OIDC_ISSUER is normally the whole configuration — the JWKS is
discovered from the issuer's well-known document. PIG_OIDC_JWKS_URI skips
discovery entirely for an air-gapped network. OIDC takes precedence over
Supabase so an on-prem install can leave the hosted values in its environment
file without them quietly taking over.

Three decisions worth stating:

Discovery is resolved lazily and the FAILURE is not cached. Doing it per
request would put the customer's identity provider on the critical path of
every API call; doing it eagerly at boot would mean their IdP rebooting takes
the CRM down with it. So it happens on first use and retries on the next
request.

The audience check is optional but warned about loudly. Without it, a token the
provider issued for ANY other application in the same tenant verifies here — a
token minted for an unrelated internal tool would be accepted as a PIG session.
It cannot be mandatory because some providers legitimately issue
single-audience tokens.

Email falls back through email, preferred_username and upn, because providers
disagree, but a preferred_username without an "@" is ignored — PIG keys
membership on the address, and a bare username must never become an account
identity.

Also fixed a warning that claimed "authentication is DISABLED" on a correctly
configured OIDC deployment. That is worse than silence: an operator who reads
it on a secure install learns to ignore the warnings. The dev bypass itself was
already correct — it keys on the resolved provider rather than on Supabase.

18 new tests, most of them about what the provider must REFUSE: a foreign
signing key, a foreign issuer, a token for a different application, an expired
token, a token with no subject, and a discovery outage that must not become
permanent. Keys are generated per test and the JWKS is served locally, so they
run offline.

Verified: production refuses to start with neither provider, starts with OIDC
alone, enforces 401 on an unauthenticated request, and warns only about the
genuinely missing admin list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 02:32:28 -07:00

106 lines
4.8 KiB
Bash

# ---------------------------------------------------------------------------
# PIG — environment
# Copy to .env and fill in. Never commit .env.
# ---------------------------------------------------------------------------
# --- Database ---------------------------------------------------------------
# PIG owns this database exclusively. Do not point it at a database shared with
# another application.
DATABASE_URL=postgres://pig:CHANGEME@localhost:5432/pig
# --- Auth (Supabase) --------------------------------------------------------
# PIG uses Supabase for authentication ONLY. It stores no passwords and issues
# no sessions of its own; it verifies incoming JWTs against the project JWKS.
#
# IMPORTANT: authorization does NOT follow from having a Supabase account.
# A user must also have a row in PIG's `users` table. If this Supabase project
# is shared with another application, that application's users get nothing here
# until they are explicitly invited.
SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co
SUPABASE_ANON_KEY=
# Service key is only needed for administrative user provisioning. Omit it and
# PIG runs fine in invite-only mode. Treat it as the most powerful secret here.
SUPABASE_SERVICE_KEY=
# --- Auth: on-premises (OIDC) ---------------------------------------------
# Set PIG_OIDC_ISSUER to authenticate against your own identity provider —
# Okta, Entra, Keycloak, Auth0, Authentik, Google Workspace, anything
# standards-compliant. It TAKES PRECEDENCE over the Supabase values above, so
# an on-prem install can leave those in place.
#
# PIG never sees a password. It verifies the token your provider issued and
# reads two things: a stable subject, and an email. Everything else — teams,
# roles, capabilities — is PIG's own data keyed on that subject, so users are
# provisioned in PIG by invite, not by your directory.
PIG_OIDC_ISSUER=
# Optional. Discovered from the issuer's /.well-known/openid-configuration when
# omitted. Set it to skip discovery entirely on an air-gapped network.
PIG_OIDC_JWKS_URI=
# STRONGLY recommended. Without it, a token your provider issued for ANY other
# application in the same tenant is accepted here as a PIG session.
PIG_OIDC_AUDIENCE=
# Comma-separated, in preference order. Defaults to email,preferred_username,upn
# which covers most providers; Entra sometimes needs upn first.
PIG_OIDC_EMAIL_CLAIMS=
# --- Application ------------------------------------------------------------
PIG_PORT=8920
PIG_PUBLIC_URL=http://localhost:8920
NODE_ENV=development
# Comma-separated emails granted platform-admin rights.
# Every address listed here MUST already have an account. An address listed but
# unregistered is a standing offer of admin to whoever claims it first.
PIG_ADMIN_EMAILS=
# Invite code gating self-serve profile creation. Rotate freely.
PIG_INVITE_CODE=
# --- Prime Intellect compute API -------------------------------------------
# Used to sync GPU availability into `inventory_listings`.
# Mint a key at https://app.primeintellect.ai/dashboard/tokens with the
# NARROWEST scope that works: `Availability -> Read`. PIG never provisions
# infrastructure and must not hold a key that could. Set an expiry.
PRIME_API_KEY=
PRIME_API_BASE=https://api.primeintellect.ai
# Rate limits are undocumented upstream; the sync backs off empirically.
PRIME_SYNC_ENABLED=false
PRIME_SYNC_INTERVAL_MINUTES=30
# --- Piggy (the in-app agent) ----------------------------------------------
# Piggy drains a leased queue and serves chat on an authenticated internal
# listener. Generate one internal token and give the same value to API + Piggy.
# Never publish the Piggy listener or put this token in a URL.
PIGGY_INFERENCE_API_KEY=
PIGGY_ENABLED=false
PIGGY_MODEL=nvidia/nemotron-3-nano-30b-a3b
PIGGY_INFERENCE_BASE=https://api.pinference.ai/api/v1
PIGGY_LEASE_SECONDS=300
PIGGY_INTERNAL_URL=http://127.0.0.1:8931
PIGGY_INTERNAL_TOKEN=
PIGGY_CHAT_HOST=127.0.0.1
PIGGY_CHAT_PORT=8931
# Only containers on a private network need this; never combine it with a
# published Piggy port.
PIGGY_CHAT_ALLOW_NON_LOOPBACK=false
# --- Slack ------------------------------------------------------------------
SLACK_BOT_TOKEN=
SLACK_SIGNING_SECRET=
SLACK_APP_TOKEN=
# --- Buzz (https://github.com/block/buzz) -----------------------------------
# Buzz agents reach PIG through the MCP server, so no PIG-specific credential is
# required. These are only for PIG pushing notifications into a Buzz relay.
BUZZ_RELAY_URL=
NOTION_CLIENT_ID=
NOTION_CLIENT_SECRET=
NOTION_REDIRECT_URI=http://localhost:8920/api/imports/notion/oauth/callback
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# Must use the PIG_PUBLIC_URL origin and exact /oauth/google/callback path.
GOOGLE_REDIRECT_URI=http://localhost:8920/oauth/google/callback
BUZZ_PRIVATE_KEY=
# Optional NIP-OA owner attestation JSON for an agent identity.
BUZZ_AUTH_TAG=