oct
Loading...
Searching...
No Matches
oct.mcp.policy_loader Namespace Reference

Functions

dict load_policy_source (str source, int timeout_s=5)
object apply_policy_overrides (object config, dict overrides)
bytes|None _fetch_url (str url, int timeout_s)
bytes|None _read_file (str path)
dict _validate_overrides (dict data)

Variables

int _POLICY_MAX_BYTES = 64 * 1024
frozenset _ALLOWED_OVERRIDE_KEYS

Detailed Description

Purpose
-------
Centralised policy loader for the ``oct-mcp`` server (Phase 5C, M-C7).

Loads policy override JSON from a local filesystem path or an HTTPS URL
at server startup. The loaded overrides are applied on top of the base
:class:`~oct.mcp.config.McpConfig` before the policy engine is
instantiated, enabling enterprise deployments to distribute a shared
security policy from a central location.

Responsibilities
----------------
- Read the policy document named by ``policy_source``, from a local path
  or an HTTPS URL, within the 64 KB cap.
- Reject HTTP URLs, oversized sources and malformed JSON.
- Filter the parsed document to :data:`_ALLOWED_OVERRIDE_KEYS`, dropping
  unknown keys and type mismatches.
- Apply the surviving overrides on top of the base ``McpConfig``.
- Fall back to built-in defaults on any failure, without raising.

Configuration
-------------
Set ``policy_source`` in ``~/.oct-mcp/config.json``::

    {
        "policy_source": "https://internal.company.com/oct-policy.json"
    }

Or provide a local path::

    {
        "policy_source": "/etc/oct/policy.json"
    }

Policy JSON schema (all fields optional)::

    {
        "profile": "strict",
        "rate_limit_per_minute": 20,
        "timeout_default_seconds": 30,
        "max_output_bytes": 524288,
        "dry_run_default_for_writes": true
    }

Only the keys listed in :data:`_ALLOWED_OVERRIDE_KEYS` are honoured.
Unknown keys are silently dropped. Type mismatches are silently ignored.

Security
--------
- HTTPS URLs only. HTTP URLs are rejected to prevent cleartext policy
  transmission.
- File size capped at 64 KB (same as ``config.json``).
- Schema is an allowlist - no arbitrary key injection possible.
- Any failure (network error, parse error, schema violation) falls back
  to built-in defaults silently without crashing the server.

Diagnostics
-----------
Domain: MCP
Levels:
    L1 - errors: load failures, schema violations
    L2 - lifecycle: policy loaded, overrides applied
    L3 - (none): resolved field detail is reported at L4
    L4 - deep trace: resolved field values

Contracts
---------
- :func:`load_policy_source` never raises - returns ``{}`` on any error.
- :func:`apply_policy_overrides` never raises - returns *config* unchanged
  on any error.
- No ``http://`` URLs are accepted - HTTPS only.

Dependencies
------------
- oct.core.diagnostics (_dbg structured logger)
- oct.mcp.config (lazy; VALID_MCP_PROFILES, to accept only a known profile override)

Function Documentation

◆ _fetch_url()

bytes | None oct.mcp.policy_loader._fetch_url ( str url,
int timeout_s )
protected
Fetch *url* via HTTPS and return raw bytes, or ``None`` on error.

Definition at line 200 of file policy_loader.py.

Here is the caller graph for this function:

◆ _read_file()

bytes | None oct.mcp.policy_loader._read_file ( str path)
protected
Read *path* from the filesystem and return raw bytes, or ``None``.

Definition at line 221 of file policy_loader.py.

Here is the caller graph for this function:

◆ _validate_overrides()

dict oct.mcp.policy_loader._validate_overrides ( dict data)
protected
Return a sanitised override dict with only allowed, well-typed values.

Definition at line 236 of file policy_loader.py.

Here is the caller graph for this function:

◆ apply_policy_overrides()

object oct.mcp.policy_loader.apply_policy_overrides ( object config,
dict overrides )
Return a new :class:`~oct.mcp.config.McpConfig` with *overrides* applied.

Parameters
----------
config
    The base :class:`~oct.mcp.config.McpConfig` instance.
overrides
    Dict of validated overrides from :func:`load_policy_source`.

Returns
-------
A new ``McpConfig`` with the override values merged in. Returns
*config* unchanged if *overrides* is empty or an error occurs.

Definition at line 168 of file policy_loader.py.

◆ load_policy_source()

dict oct.mcp.policy_loader.load_policy_source ( str source,
int timeout_s = 5 )
Load policy override JSON from *source*.

Parameters
----------
source
    A local filesystem path or an ``https://`` URL. ``http://`` URLs
    are rejected. Local paths may be absolute or relative.
timeout_s
    Network timeout in seconds for HTTPS requests (default 5).

Returns
-------
A ``dict`` containing only the keys in :data:`_ALLOWED_OVERRIDE_KEYS`
with validated values. Returns ``{}`` on any failure.

Definition at line 116 of file policy_loader.py.

Here is the call graph for this function:

Variable Documentation

◆ _ALLOWED_OVERRIDE_KEYS

frozenset oct.mcp.policy_loader._ALLOWED_OVERRIDE_KEYS
protected
Initial value:
1= frozenset({
2 "profile",
3 "rate_limit_per_minute",
4 "timeout_default_seconds",
5 "max_output_bytes",
6 "dry_run_default_for_writes",
7})

Definition at line 102 of file policy_loader.py.

◆ _POLICY_MAX_BYTES

int oct.mcp.policy_loader._POLICY_MAX_BYTES = 64 * 1024
protected

Definition at line 98 of file policy_loader.py.