1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
//! # secureops-napi
//!
//! The **Ring 1** in-process engine surface (PRODUCT.md A.2, Part G Phase 1:
//! *"Rust core behind napi"*). This crate is built as a Node native addon
//! (`crate-type = ["cdylib", "rlib"]`) and loaded by a thin TypeScript shim that
//! replaces the legacy `@adversa/secureops` audit body with a single FFI call.
//!
//! ## Why a plain-Rust seam
//!
//! The actual `#[napi]` wrappers (provided by `napi-derive`) are intentionally
//! *not* compiled in this scaffold — the `napi` / `napi-derive` / `napi-build`
//! crates require a Node toolchain and pull a large native build, which would
//! break the offline-fast workspace build. So the public functions here are
//! ordinary Rust (`String`-in / `String`-out, JSON on the wire). Each is annotated
//! with the `#[napi]` attribute it *will* carry once Phase 1 wiring lands, e.g.:
//!
//! ```ignore
//! #[napi]
//! pub async fn audit_to_json(state_dir: String, deep: bool, fix: bool) -> napi::Result<String> {
//! Ok(crate::audit_to_json(state_dir, deep, fix).await)
//! }
//! ```
//!
//! Keeping the logic in plain functions means the standalone `clap` binary
//! (`secureops-cli`) and unit tests can drive the identical code path without
//! Node, and the FFI layer stays a thin, generated shim.
//!
//! The full OpenClaw plugin surface (lifecycle hooks, command dispatch, MCP
//! tools — the TS `legacyPlugin`) is ported in [`plugin`]; the TS shim wires
//! OpenClaw's callbacks to those functions.
//!
//! ## Trust model (PRODUCT.md A.2)
//!
//! Ring 1 shares the agent's fate: it gives fast, in-context audit + monitoring
//! while the host process is healthy but provides **no enforcement**. Enforcement
//! lives in the Ring 2 daemon. This addon's job is *feedback and convenience*.
//!
//! ## Wire-format contract (PRODUCT.md A.5 / A.3)
//!
//! Everything crossing the FFI boundary is JSON produced by
//! [`secureops_core::AuditReport::to_json_pretty`], so the shim and a future
//! Rust daemon read/write byte-compatible `<stateDir>/.secureops/` artifacts.
//! Treat the JSON field names as frozen.
use ;
use Arc;
/// SecureOps report version surfaced to the TS shim (becomes `secureopsVersion`
/// in the emitted [`AuditReport`]). Matches the TS tool's hardcoded value so the
/// JSON wire output is identical regardless of which side produced it.
pub const SECUREOPS_VERSION: &str = "2.2.0";
/// Bundled IOC database (same asset the CLI embeds), so the Ring-1 audit path
/// matches the CLI's IOC coverage.
pub const BUNDLED_IOC: &str = include_str!;
pub
pub
/// Run a full read-only audit and return the report as pretty JSON.
///
/// This is the primary Ring 1 entrypoint (PRODUCT.md B.2 *Audit*). In the
/// Phase 1 build it is wrapped by a `#[napi] pub async fn` so the TS shim can
/// `await secureops.auditToJson(stateDir, deep, fix)` in place of its legacy
/// audit body.
///
/// Pipeline it will drive (PRODUCT.md B.2):
/// 1. build an `Arc<dyn AuditContext>` from [`secureops_fs`] (real `tokio::fs`),
/// 2. assemble the [`Check`] registry from [`secureops_checks`],
/// 3. call [`secureops_core::run_audit`] (panicking checks degrade to INFO,
/// the run never aborts),
/// 4. serialize via [`AuditReport::to_json_pretty`].
///
/// # Wire shape
/// Returns the JSON of an [`AuditReport`]; on a fatal harness error it returns a
/// JSON error envelope (never panics across the FFI boundary).
///
/// Future FFI signature:
/// ```ignore
/// #[napi]
/// pub async fn audit_to_json(state_dir: String, deep: bool, fix: bool) -> napi::Result<String>;
/// ```
pub async
/// Run the audit and return the structured [`AuditReport`] (no serialization).
///
/// Internal seam shared by [`audit_to_json`] and the standalone CLI so both go
/// through one code path. Splitting JSON encoding out keeps the FFI wrapper a
/// trivial `to_json_pretty` call and lets the CLI render a human console report
/// from the same value.
pub async
/// Build the default [`Check`] registry (one boxed impl per audit category).
///
/// Mirrors the TS tool's check set (PRODUCT.md B.2 step 2). The concrete impls
/// live in [`secureops_checks`]; this scaffold just declares the seam the FFI
/// and CLI consume.
/// JSON of the current SecureOps IOC database version metadata, for the shim's
/// `--version` / health output (PRODUCT.md B.1 step 4 bundled IOC DB).
///
/// Future FFI signature: `#[napi] pub fn ioc_db_info() -> napi::Result<String>;`