# ═══════════════════════════════════════════════════════════════ # OpenVibe.Watch — Environment Configuration # Copy to .env and fill in values. # In production this lives at /etc/openvibe/watch.env (0600); the systemd unit sets # NODE_ENV and PORT itself. # ═══════════════════════════════════════════════════════════════ # Server PORT=4730 HOST=127.0.0.1 NODE_ENV=development #BASE_URL=https://openvibe.watch # The public site sits behind nginx (and Cloudflare): trust one proxy hop for the real client address. #TRUST_PROXY=1 # Identity — OpenVibe.Network signs the tokens this service verifies. Service tokens (svc:…) carry # capability grants (audience openvibe.watch); a person's bearer token (usr_…) is verified for the # same audience and acts on the watches it owns. OV_NETWORK_URL=https://openvibe.network OV_NETWORK_INTERNAL_URL=http://127.0.0.1:4000 #OV_NETWORK_ISSUER=https://openvibe.network # The JWKS the service verifies tokens against; by default Network's internal JWKS # (OV_NETWORK_INTERNAL_URL/api/.well-known/jwks). openvibe-sdk/auth caches it and keeps it fresh. #OV_NETWORK_JWKS_URL=https://openvibe.network/api/.well-known/jwks # Per-actor limits (server/api/actor-limits.js): API reads one app or module (app:…, mod:…) may make per # minute and per hour; past them 429 rate_limited with Retry-After. First-party services (svc:…) are not # counted on reads; writes have their own numbers (README). #WATCH_LIMITS_MINUTE=120 #WATCH_LIMITS_HOUR=3000 # This service's own principal (svc:watch) — publishes watch.* events (events.event.publish) — and # the public site's sign-in client. Keep OV_OAUTH_CLIENT_ID=watch and set the secret in # /etc/openvibe/watch.env (0600): the site exchanges a person's sign-in code for a Network token with it. OV_OAUTH_CLIENT_ID=watch OV_OAUTH_CLIENT_SECRET= # The site's sign-in callback (default BASE_URL + /auth/callback; register this exact URI on the # Network client), and the scope and session audience a person's Network token is verified for. #OV_OAUTH_REDIRECT_URI=https://openvibe.watch/auth/callback #OV_OAUTH_SCOPE=profile #OV_SESSION_AUDIENCE=openvibe.network # The site's session cookie is Secure in production (https) by default; set false only in development. #COOKIE_SECURE=true # Store (PostgreSQL, ADR-035), written by OpenVibe.Host roles/data/add-service.sh watch: the runtime role through # PgBouncer, the owner on a direct connection (migrations), and Valkey (shared limit counters). # Without DATABASE_URL, development uses an embedded PGlite database in data/pglite. DATABASE_URL= DATABASE_DIRECT_URL= VALKEY_URL= VALKEY_PREFIX= # OpenVibe.Events. The outbox relay runs only when EVENTS_URL is set. #EVENTS_URL=http://127.0.0.1:4300 #EVENTS_RELAY_INTERVAL_MS=2000 # OpenVibe.Events → Watch (ADR-033 account export and deletion): signs a delivery to POST /internal/events # (comma-separated for rotation, 32+ characters each). Unset: the route answers 503 and no subscription is created. #WATCH_EVENTS_SECRET= # Check worker (in-process scheduler) #WATCH_WORKER=on #WATCH_TICK_MS=5000 #WATCH_MAX_CONCURRENT=8 #WATCH_MAX_BACKOFF_MS=21600000 # Fetching (the SSRF-guarded fetcher every carrier goes through) #WATCH_USER_AGENT=OpenVibeWatch/0.1.0 (+https://openvibe.watch; Contact@OpenVibe.Network) #WATCH_FETCH_TIMEOUT_MS=20000 #WATCH_MAX_BYTES=5242880 #WATCH_MAX_REDIRECTS=5 # Least time between two requests to one host, whatever a watch says. #WATCH_HOST_MIN_INTERVAL_MS=1000 #WATCH_ALLOWED_PORTS=80,443 # Exact hosts/IPs allowed to resolve to private/loopback addresses. Leave EMPTY in production. #WATCH_ALLOW_PRIVATE_HOSTS= # Observations #WATCH_OBSERVATIONS_MAX_PER_CHECK=100 #WATCH_RETENTION_DEFAULT_DAYS=90 # Registry: how many watches one owner (a person, an agent or a service) may hold. The cadence floor # (15 minutes) is fixed in the registry. #WATCH_MAX_PER_OWNER=50 # OpenVibe.Run — the expensive checks (browser/code), step 6. Never used until then: a run source # answers watch.carrier_unavailable and nothing is executed. #WATCH_RUN_URL=http://127.0.0.1:4920 #WATCH_RUN_OAUTH_CLIENT_SECRET= # Source credentials: a watch's source.auth names the variable (auth.env), never the value. Names # must start with WATCH_CRED_. Read at fetch time, never stored, never logged. #WATCH_CRED_EXAMPLE_API_KEY= # Webhook keys: a webhook action signs its delivery with the variable its secret_env names. Names must # start with WATCH_HOOK_ and the value hold at least 32 characters. #WATCH_HOOK_EXAMPLE_SECRET= # A receiver answers within this, or the attempt is retried on the backoff. #WATCH_WEBHOOK_TIMEOUT_MS=10000 # Email in (agent plan A3): a webhook watch may have an address at WATCH_MAIL_DOMAIN. Cloudflare Email Routing hands each # message to the mail Worker (edge/mail-worker.mjs, deployed by deploy/mail-worker.js), which posts it to /hooks/email # signed with this secret (at least 32 characters; the Worker's INGRESS_SECRET). Unset: no email in. #WATCH_MAIL_INGRESS_SECRET= #WATCH_MAIL_DOMAIN=openvibe.watch # OpenVibe.Actor's internal address, for actor-task and actor-agent actions (Watch needs actor.task.create and actor.agent.run grants). #WATCH_ACTOR_URL=http://127.0.0.1:4950 # Who may use which named secret (server/secret-grants.js). A name is not a capability: without a grant # nobody can use it. A credential needs owners and the origins it may be sent to; a webhook key, owners. # Owners are usr_ or agt_ subjects; origins are scheme://host[:port]. #WATCH_SECRET_GRANTS={"WATCH_CRED_EXAMPLE_API_KEY":{"owners":["usr_..."],"origins":["https://api.example.com"]},"WATCH_HOOK_EXAMPLE_SECRET":{"owners":["usr_..."]}} # Usage readings → OpenVibe.Billing (server/billing.js): one check-operation reading per completed check, relayed # every WATCH_BILLING_INTERVAL_MS (0, the default, is off: nothing is queued) with this service's client credentials # (OV_OAUTH_CLIENT_ID/OV_OAUTH_CLIENT_SECRET above; Network grants billing.usage.record). Without the URL or the # secret, readings are queued and stay local. #OV_BILLING_INTERNAL_URL= #OV_BILLING_AUDIENCE= #WATCH_BILLING_TIMEOUT_MS= #WATCH_BILLING_INTERVAL_MS= # Provider-rate evidence (server/provider-rates.js, plan P6). 0 (the default) is off: the module is not # created, no route is mounted and nothing is seeded. 1 mounts the API and the worker, but a source still # starts disabled until a person reads its terms/robots notes and enables it (PATCH .../sources/:key). #WATCH_PROVIDER_RATES=0 #WATCH_PROVIDER_RATES_TICK_MS=60000 #WATCH_PROVIDER_RATES_MAX_BYTES=8388608 #WATCH_PROVIDER_RATES_POLL_SEC=21600 #WATCH_PROVIDER_RATES_STALE_SEC=43200