refactor(engine): inline policies on DetectionInput; drop /policies resource#276
Merged
Conversation
…esource
Policies stop being a persisted resource: the caller submits the
full inline policy bodies on every detect call, the engine snapshots
digests onto the persisted detection record, and the audit references
rules by `(policy_name, rule_name)` instead of `(policy_id, rank)`.
New types in `nvisy_engine::policy`:
- `AnyPolicy` — modality-erased sum (Text/Tabular/Image/Audio)
mirroring `AnyAudit`. Submitted inline on every detect call.
- `PolicyDigest { name, version }` — header card stored on
`DetectionResult`. No rule bodies.
- `PolicyDecisionRef { policy_name, rule_name: Option }` — stamped
on every policy-driven `AuditEntry`. `rule_name` is `None` when the
policy's `default_action` fallback fired.
- `validate_policy_namespace` — runs at the top of `Engine::detect`,
rejects duplicate policy names within a submission and duplicate
rule names within a policy. The audit's identity-by-name guarantee
depends on these invariants.
`Policy::id: Uuid` replaced with `Policy::name: HipStr<'static>`.
`PolicyRule` gains a required `name: HipStr<'static>` field. `RuleRank`
deleted. `HipStr` chosen for the names so audit-heavy passes share
refcounts rather than allocating per-entity.
Server-side:
- `/api/v1/policies[/{id}]` removed (4 endpoints + request/response
types + path helper + `service/mod.rs` doc trail).
- `POST /api/v1/detections` body's `policies: Vec<Uuid>` becomes
`policies: Vec<AnyPolicy>` — inline submission only.
Registry-side:
- `register_policy`/`read_policy`/`unregister_policy`/
`unregister_all_policies`/`list_policies`/
`list_policies_with_summary` deleted.
- `policies_ks` Fjall keyspace + `policy_cache` removed.
- `ResourceCache`/`ResourceGuard` deleted (policy persistence was
its only consumer).
The detect→redact handoff carries the full `Vec<AnyPolicy>` through
an internal `DetectionHandoff` shape so the redact pipeline can
re-evaluate operator specs without the caller re-submitting them.
After a process restart the in-memory record is gone and the
redaction can't proceed — that was already the existing semantic;
this PR just makes it explicit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Follows up the inline-policies refactor with a sweep that addresses the audit findings (no functional change). - PolicyStore::from_any_policies consumes Vec<AnyPolicy> by value and moves Policy<M> straight into Arc::new(p) — no deep clones. - Detection record holds Arc<PolicyStore> + Vec<PolicyDigest> built once at register_pending time. Redact handoff is an Arc::clone of the store; build_policy_store is gone. - DetectionPipeline::register_pending now consumes DetectionInput and returns a PreparedDetection that execute consumes — the AnyPolicy bodies are touched exactly once on the detect side. - SharedData::policies typed as Arc<PolicyStore>; dead with_policy / with_policies builder methods removed. - PolicyStore public surface reduced to construction + resolve: insert / set / get / len / is_empty / new dropped. tests rewritten around from_any_policies + resolve. - validate_policy_namespace stops allocating an intermediate Vec<&str> per policy; uses a shared check_rule_names helper. - AnyPolicy::name returns &str. PolicyDigest and PolicyDecisionRef drop unused Eq / PartialEq derives. - nvisy-server README rewritten to match nvisy-engine / nvisy-codec style (tagline + Overview prose + standard footer; no endpoint or feature tables). - OpenAPI 'policies' tag and the policies mention in service/mod.rs docs removed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Approach
Two commits, no functional drift between them.
1. Inline policies + audit-by-name (commit `e8cd7d28`). New types in `nvisy_engine::policy`:
Server-side: `/api/v1/policies[/{id}]` removed; `POST /api/v1/detections` body's `policies: Vec` becomes `Vec`. Registry-side: `register_policy` / `read_policy` / `unregister_policy` / `unregister_all_policies` / `list_policies` / `list_policies_with_summary` / `policy_cache` / `policies_ks` / `ResourceCache` / `ResourceGuard` deleted.
The detect→redact handoff carries the prepared store through an internal `DetectionHandoff` so the redact pipeline can re-evaluate operator specs without the caller re-submitting policies. After a process restart the in-memory record is gone and the redaction can't proceed — that was already the existing semantic; this PR just makes it explicit.
2. Cut clones; tighten the store surface (commit `85c6eaa7`). Follow-up sweep that addresses an audit pass on the first commit:
Net diff
`-1110 / +519` across 31 files. Six files deleted entirely: `registry/resource_cache.rs`, `handler/policies.rs`, `handler/request/policies.rs`, `handler/response/policies.rs`, `build_policy_store` (was internal). `RuleRank` and the `set` / `insert` / `get` / `len` PolicyStore surface gone.
Test plan