Dual Policy Model
Relevant source files
The following files were used as context for generating this wiki page:
The Dual Policy Model is a core architectural pattern in Honmoon where the security policy is defined twice—once in Rust for the data plane and once in TypeScript for the control plane. This redundancy ensures that each language can interact with the policy natively while maintaining a shared structure. The two models are kept in sync manually, with a JSON Schema serving as the future single source of truth to prevent architectural drift.
This model allows the Rust data plane to perform high-performance wire-level enforcement and the TypeScript control plane to handle management tasks like policy validation, audit querying, and dashboard rendering.
Sources: wiki/deep-dive/architecture.md, ARCHITECTURE.md:95-97
Model Structure & Types
The model describes five primary entities: Policy, Egress, Rule, Verdict, and Facts. These entities are mirrored across both Rust and TypeScript implementations.
Class Diagram: Policy Schema
The following diagram illustrates the relationship between the core components of the policy model as defined in both environments.
Mapping of Implementations
| Concept | Rust (honmoon-core) | TypeScript (@honmoon/policy) | JSON Schema ($defs) |
|---|---|---|---|
| Verdict | enum Verdict | type Verdict | verdict |
| Egress | struct Egress | interface Egress | properties.egress |
| Rule | struct Rule | interface Rule | rule |
| Policy | struct Policy | interface Policy | Root object |
| Facts | struct Facts | interface FactsSummary | N/A (Internal) |
Sources: crates/honmoon-core/src/lib.rs:14-70, packages/policy/src/index.ts:7-31, packages/policy/schema/policy.schema.json:23-39
Implementation Details
Rust Data Plane (honmoon-core)
In Rust, the model is implemented using strongly-typed structs and enums with serde derives for YAML and JSON serialization. The Verdict enum is the fundamental unit of decision-making, defaulting to Deny to enforce a "fail-closed" security posture.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum Verdict {
Allow,
#[default]
Deny,
Pause,
}
Sources: crates/honmoon-core/src/lib.rs:14-23
TypeScript Control Plane (@honmoon/policy)
The TypeScript implementation provides the types used by the dashboard and the management API. It mirrors the Rust logic, including the runtime decision model used for auditing and pending approvals.
export type Verdict = 'allow' | 'deny' | 'pause';
export interface Rule {
name: string;
endpoint: string;
condition: string;
verdict: Verdict;
}
Sources: packages/policy/src/index.ts:7-17
Architectural Invariants & Sync
The Dual Policy Model is governed by several critical invariants designed to maintain system integrity:
- Manual Synchronization (TD-001): Currently, changes to the policy shape must be applied to both the Rust and TypeScript codebases manually. Failure to do so leads to "silent policy divergence."
- Single Source of Truth: The
policy.schema.jsonis the intended authority for validation across both planes. - Fail-Closed Posture: Both implementations must ensure that the absence of a match or a processing error results in a
Denyverdict.
Sources: ARCHITECTURE.md:95-97, wiki/deep-dive/architecture.md, wiki/deep-dive/policy-engine.md
Data Flow: Decision Seam
The model acts as a "seam" between protocol parsers and the enforcement gateway. The proxy extracts Facts from the wire, which are then evaluated against the Policy to produce a Verdict.
Summary
The Dual Policy Model provides a robust, polyglot foundation for Honmoon. By maintaining mirrored structures in Rust and TypeScript, the project achieves high-performance traffic enforcement while enabling a rich, type-safe management interface. The ongoing effort to automate this sync via JSON Schema (TD-001) is the primary roadmap item for this module.