> ## Documentation Index
> Fetch the complete documentation index at: https://memproof.kyberon.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Policy Hot-Reload

> Automatically reload policy changes without restart

Memproof includes a `PolicyWatcher` that monitors your YAML policy file and automatically reloads it when changes are detected. This allows you to update policy rules, risk thresholds, and default behaviors in production without restarting your application.

## How It Works

The `PolicyWatcher` runs a background loop that periodically computes the SHA-256 hash of the policy file. When the hash changes, the watcher parses the new file, validates it, and swaps the active policy configuration. If the new file is invalid, the watcher keeps the previous valid configuration and calls an error callback.

## Basic Usage

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    from memproof.policy.hot_reload import PolicyWatcher

    watcher = PolicyWatcher(
        "./memproof.yaml",
        on_reload=lambda cfg: print("Reloaded!"),
    )
    watcher.start(interval=5.0)

    # Your application runs here...

    # When shutting down
    watcher.stop()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { PolicyWatcher } from "@kyberon/memproof";

    const watcher = new PolicyWatcher({
        policyPath: "./memproof.yaml",
        onReload: (config) => console.log("Reloaded!"),
        intervalMs: 5000,
    });

    watcher.start();

    // Your application runs here...

    // When shutting down
    watcher.stop();
    ```
  </Tab>
</Tabs>

## Change Detection

The watcher uses SHA-256 hashing to detect file changes. On each tick it reads the file, computes the hash, and compares it to the last known hash. This approach avoids false reloads caused by file metadata changes (modified timestamps, permissions) that do not affect the file content.

| Event                      | Behavior                                        |
| -------------------------- | ----------------------------------------------- |
| File content changes       | New config is parsed, validated, and swapped in |
| File unchanged             | No action taken                                 |
| File metadata changes only | No action taken (hash is content-based)         |
| File deleted or unreadable | Error callback fired, previous config retained  |

## Error Handling

Provide an `on_error` callback to handle cases where the updated policy file is invalid or unreadable. The watcher will continue running and retain the last valid configuration.

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    from memproof.policy.hot_reload import PolicyWatcher

    def handle_reload(cfg):
        print(f"Policy reloaded: {len(cfg.rules)} rules active")

    def handle_error(err):
        print(f"Policy reload failed: {err}")
        # Alert your monitoring system, log the error, etc.

    watcher = PolicyWatcher(
        "./memproof.yaml",
        on_reload=handle_reload,
        on_error=handle_error,
    )
    watcher.start(interval=10.0)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { PolicyWatcher } from "@kyberon/memproof";

    const watcher = new PolicyWatcher({
        policyPath: "./memproof.yaml",
        onReload: (config) => {
            console.log(`Policy reloaded: ${config.rules.length} rules active`);
        },
        onError: (err) => {
            console.error(`Policy reload failed: ${err.message}`);
            // Alert your monitoring system, log the error, etc.
        },
        intervalMs: 10000,
    });

    watcher.start();
    ```
  </Tab>
</Tabs>

## Integration with Memproof

To wire the watcher into a running Memproof instance, pass the instance's `reload_policy` method as the `on_reload` callback. This ensures the orchestrator, risk engine, and policy engine all pick up the new configuration atomically.

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    from memproof import Memproof
    from memproof.policy.hot_reload import PolicyWatcher

    mp = Memproof(policy="./memproof.yaml", adapter="in_memory")

    watcher = PolicyWatcher(
        "./memproof.yaml",
        on_reload=mp.reload_policy,
        on_error=lambda err: print(f"Reload failed: {err}"),
    )
    watcher.start(interval=5.0)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { Memproof, PolicyWatcher } from "@kyberon/memproof";

    const mp = new Memproof({
        policy: "./memproof.yaml",
        config: { adapter: "in_memory" },
    });

    const watcher = new PolicyWatcher({
        policyPath: "./memproof.yaml",
        onReload: (config) => mp.reloadPolicy(config),
        onError: (err) => console.error(`Reload failed: ${err.message}`),
        intervalMs: 5000,
    });

    watcher.start();
    ```
  </Tab>
</Tabs>

<Note>
  The policy swap is atomic. In-flight operations that already passed policy evaluation will complete under the old policy. New operations will immediately use the reloaded policy.
</Note>

<Warning>
  Set the polling interval based on your operational needs. Very short intervals (under 1 second) add unnecessary file I/O. For most deployments, 5--10 seconds provides a good balance between responsiveness and overhead.
</Warning>

<Tip>
  Combine hot-reload with version-controlled policy files. Push a policy change to your Git repository, have your CI/CD pipeline deploy the updated YAML file, and the `PolicyWatcher` will pick it up automatically -- no rolling restarts required.
</Tip>
