-
Notifications
You must be signed in to change notification settings - Fork 411
Description
Problem Statement
The sandbox policy has three separate Rust struct hierarchies representing the same YAML shape: Deserialize-only types in navigator-policy for parsing user-authored YAML, prost-generated types from sandbox.proto for wire/storage, and Serialize-only types in navigator-cli for ncl sandbox policy get --full output. These were written independently and have silently diverged — the input YAML uses filesystem_policy but the output YAML writes filesystem (matching the proto field name), breaking round-tripping. The output path also silently drops allowed_ips and the name field on network policy rules.
Technical Context
The proto layer in the middle is unavoidable (it serves as the wire/storage format), but the Input and Output struct hierarchies are mirrors of each other — one implements Deserialize, the other Serialize — with manual field-by-field conversion functions on each side. A single set of structs in navigator-policy that derive both Serialize and Deserialize would eliminate the duplication and make round-tripping correct by construction. The filesystem_policy naming also flows into the OPA/Rego layer (data.filesystem_policy in rego rules and proto_to_opa_data_json()), so the canonical YAML key needs to be preserved.
Affected Components
| Component | Key Files | Role |
|---|---|---|
| navigator-policy | crates/navigator-policy/src/lib.rs |
Input YAML structs (PolicyFile, FilesystemDef, etc.) and YAML→proto conversion |
| navigator-cli | crates/navigator-cli/src/run.rs |
Output YAML structs (PolicyYaml, FilesystemYaml, etc.) and proto→YAML conversion |
| proto | proto/sandbox.proto |
Wire format — field named filesystem (not filesystem_policy) |
| navigator-sandbox (OPA) | crates/navigator-sandbox/src/opa.rs |
Manual proto→JSON with "filesystem_policy" key for Rego evaluation |
| Rego rules | dev-sandbox-policy.rego |
References data.filesystem_policy |
Proposed Approach
Consolidate the Input (Hierarchy A) and Output (Hierarchy C) structs into a single set of types in navigator-policy that derive both Serialize and Deserialize. Use #[serde(rename = "filesystem_policy")] (or keep the struct field named filesystem_policy) so the canonical YAML key is preserved. Move the proto→YAML conversion (policy_to_yaml) into navigator-policy alongside the existing YAML→proto conversion, so both directions live in one place. The CLI then just calls the shared serializer. The OPA JSON builder (proto_to_opa_data_json) is a separate concern and should not be changed in this work — it already uses the correct key name.
Scope Assessment
- Complexity: Medium
- Confidence: High — clear path, no design ambiguity
- Estimated files to change: 3-4 (
navigator-policy/src/lib.rs,navigator-cli/src/run.rs,Cargo.tomlif needed, tests) - Issue type:
refactor
Risks & Open Questions
allowed_ipsandnamefield data loss: The output structs silently drop these. The consolidated types must include all fields from both the input and proto definitions. Verify no other fields are missing.- Stale checked-in generated proto code:
crates/navigator-core/src/proto/navigator.sandbox.v1.rsis completely out of date (old schema withNetworkPolicy/NetworkModethat no longer exist). Not used at runtime but misleads developers. Consider deleting or regenerating as a follow-up. InferencePolicy.api_patterns: The proto has this field but it has no YAML representation in either direction today. The consolidated types should include it for completeness, but it can be#[serde(default, skip_serializing_if)]for now.- BTreeMap vs HashMap: Output uses
BTreeMapfor deterministic ordering; input usesHashMap. The consolidated type should useBTreeMapfor stable YAML output. deny_unknown_fields: The input types use#[serde(deny_unknown_fields)]. This is strict and good for input validation but means adding new optional fields requires a version bump or feature flag. Keep this behavior.
Test Considerations
- Round-trip test: parse
dev-sandbox-policy.yaml→ proto → YAML string → parse again → assert equality - Ensure
allowed_ipsandnamefields survive the round-trip - Existing OPA tests in
navigator-sandbox/src/opa.rsshould continue passing (they use inline YAML withfilesystem_policykey) - CLI
policy get --fulloutput should be parseable byparse_sandbox_policy()
Created by spike investigation. Use build-from-issue to plan and implement.