oc_chat
Loading...
Searching...
No Matches
oc_chat._env_guard Namespace Reference

Functions

bool _is_security_authority_var (str name)
None load_dotenv_guarded ()

Variables

frozenset _AUTHORITY_EXACT

Detailed Description

Out-of-band guard for security-authority environment variables (M8.0; F33/F72).

Purpose
-------
OC Chat loads a repo-local ``.env`` at import for convenience (API keys, session
dir, etc.). But the threat model treats the workspace — including its ``.env`` —
as attacker-influenceable, so a ``.env`` must NOT be able to set the variables
that govern the security posture or the egress destination:

* ``OC_CHAT_PROFILE`` and ``OC_CHAT_ALLOW_REMOTE_ENDPOINTS`` (the risk profile /
  remote-endpoint opt-in must be operator-out-of-band, F33);
* provider endpoint URLs (``*_BASE_URL`` / ``*_BASE_URLS``) — a ``.env``-set
  base URL would redirect the provider transcript + API key (F72);
* the transport-trust family (``HTTP(S)_PROXY`` / ``ALL_PROXY`` / ``NO_PROXY`` /
  ``SSL_CERT_*`` / ``REQUESTS_CA_BUNDLE`` / ``CURL_CA_BUNDLE``) and the
  package-index family (``PIP_*`` / ``UV_INDEX_URL`` / ``NPM_CONFIG_REGISTRY``).

:func:`load_dotenv_guarded` loads ``.env`` but strips any such variable that the
``.env`` *introduced* (was not already present in the real process environment),
so these remain settable only out-of-band by the operator's launch environment.
Non-authority variables (e.g. ``DEEPSEEK_API_KEY``, ``OC_CHAT_SESSIONS_DIR``)
load from ``.env`` as before.

This module has no ``oc_chat`` dependencies so it is import-safe from
``oc_chat/__init__`` before the rest of the package initializes. It does import
``oc_diagnostics``, which is a standalone zero-dependency package that
``oc_chat/__init__`` has already loaded by the time it reaches this module.

Responsibilities
----------------
- :data:`_AUTHORITY_EXACT` — the exact names a workspace ``.env`` may never
  set. Enrolling a name here is a security-posture decision: it declares that
  the value is the operator's out-of-band authority alone.
- :func:`_is_security_authority_var` — the predicate over that set plus the
  three name FAMILIES (provider ``*_BASE_URL``, ``PIP_*``).
- :func:`load_dotenv_guarded` — load ``.env``, then strip every authority
  variable the file introduced.

Contracts
---------
- A real-process-environment value always wins; ``.env`` can neither set nor
  override an authority variable, only fail to.
- The predicate is matched case-insensitively on the UPPER-cased name, so a
  lower-case ``.env`` key cannot slip an authority variable past it.
- This module imports nothing from ``oc_chat``. It runs before the package is
  initialised, and a dependency here would be a circular import at the one
  moment the guard has to work.

Dependencies
------------
- oc_diagnostics (structured debug logging via _dbg)
- dotenv (lazy; optional python-dotenv loader, absent means the process environment is used as-is)

Diagnostics
-----------
Domain: OC_CHAT.MAIN
Levels:
    L2 — lifecycle events
    L3 — semantic details
    L4 — deep tracing (module-load coverage marker)

Function Documentation

◆ _is_security_authority_var()

bool oc_chat._env_guard._is_security_authority_var ( str name)
protected
True if *name* governs the security posture or egress destination and so
must be operator-out-of-band, never set from a workspace ``.env``.

Definition at line 94 of file _env_guard.py.

Here is the caller graph for this function:

◆ load_dotenv_guarded()

None oc_chat._env_guard.load_dotenv_guarded ( )
Load ``.env`` but refuse to let it set security-authority variables.

A real-process-environment value always wins (``override=False``); any
authority variable the ``.env`` *introduces* (absent before the load) is
removed afterward, so ``.env`` can neither set nor override it.

Definition at line 107 of file _env_guard.py.

Here is the call graph for this function:

Variable Documentation

◆ _AUTHORITY_EXACT

frozenset oc_chat._env_guard._AUTHORITY_EXACT
protected
Initial value:
1= frozenset({
2 "OC_CHAT_PROFILE", "OC_CHAT_ALLOW_REMOTE_ENDPOINTS",
3 "OC_CHAT_EXTERNAL_CONTENT_GATE", # F67 gate disable is operator-OOB-only
4 "OC_CHAT_MAX_TOOL_CALLS_CEILING", # §4.4(a) per-turn-cap ceiling is OOB-only (F33/§5.4)
5 "OC_CHAT_SESSION_COST_CEILING_USD", # CAPS-01: the $ hard cap is OOB-raisable only (F33/§5.4)
6 "OC_CHAT_STALL_REPEAT_CEILING", # CAPS-02: stall threshold is OOB-raisable only
7 "OC_CHAT_STALL_ERROR_STREAK_CEILING", # CAPS-02: stall threshold is OOB-raisable only
8 "OC_CHAT_STALL_NO_PROGRESS_CEILING", # CAPS-02: stall threshold is OOB-raisable only
9 "OC_CHAT_PIP_INDEX_URL", # SUPPLY-02/F78: the trusted package index is OOB-replaceable only
10
11 "HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "NO_PROXY",
12 "SSL_CERT_FILE", "SSL_CERT_DIR", "REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE",
13 "UV_INDEX_URL", "NPM_CONFIG_REGISTRY",
14})

Definition at line 78 of file _env_guard.py.