diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5e5092f04d5..ab57f0302f1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,365 +1,344 @@
-# Contributing to osquery β OpenFrame Edition
+# Contributing to osquery (OpenFrame-Enhanced)
-Thank you for contributing to osquery with OpenFrame! This guide covers everything you need to get started: code style, branching conventions, commit format, testing requirements, and the pull request process.
+Thank you for your interest in contributing to the OpenFrame-enhanced distribution of osquery! This guide covers everything you need to get started: setting up your environment, understanding the codebase, following code style conventions, and submitting changes.
---
## Community First
-All collaboration happens on the **OpenMSP Slack community** β not GitHub Issues or GitHub Discussions.
+This project is managed through the **OpenMSP Slack community**. GitHub Issues and GitHub Discussions are **not used**.
-| Resource | Link |
-|---|---|
-| π¬ OpenMSP Community Slack | [Join here](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) |
-| π OpenMSP Website | [https://www.openmsp.ai/](https://www.openmsp.ai/) |
+- **Slack**: [Join OpenMSP](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA)
+- **Platform**: [https://www.openmsp.ai/](https://www.openmsp.ai/)
-Before starting significant work, please discuss your changes in Slack to align with the team's roadmap.
+Before opening a pull request, please discuss your planned change in the Slack community. This ensures alignment on scope, approach, and priority.
---
-## Development Setup
+## Development Environment Setup
-### Hardware Requirements
+### System Requirements
-| Tier | RAM | CPU Cores | Disk |
-|---|---|---|---|
-| **Minimum** | 24 GB | 6 cores | 50 GB |
-| **Recommended** | 32 GB | 12 cores | 100 GB |
+| Component | Minimum | Recommended |
+|-----------|---------|-------------|
+| **RAM** | 24 GB | 32 GB |
+| **CPU Cores** | 6 cores | 12 cores |
+| **Disk Space** | 50 GB | 100 GB |
### Required Tools
-| Tool | Minimum Version | Purpose |
-|---|---|---|
-| CMake | 3.21+ | Build system generator |
-| Python | 3.8+ | Code generation scripts |
-| Git | 2.x | Source control |
-| C++ Compiler | GCC 9+ / Clang 10+ / MSVC 2019+ | C++17 compilation |
-| Ninja | 1.10+ | Fast parallel builds |
-| OpenSSL | 1.1.1+ | TLS + AES-256-GCM (OpenFrame layer) |
-| clang-format | β | Code formatting (CI enforced) |
+| Tool | Version | Purpose |
+|------|---------|---------|
+| **CMake** | β₯ 3.21 | Build system generator |
+| **Clang** | β₯ 13 | C++ compiler (C++17 required) |
+| **Python 3** | β₯ 3.6 | Code generation scripts |
+| **OpenSSL** | β₯ 1.1.1 | AES-256-GCM encryption |
+| **Git** | β₯ 2.x | Source control |
-### Quick Setup
+### Install Dependencies
+
+**Linux (Ubuntu/Debian):**
+
+```bash
+sudo apt-get update && sudo apt-get install -y \
+ build-essential \
+ cmake \
+ clang-13 \
+ clang++-13 \
+ lld-13 \
+ python3 \
+ python3-pip \
+ git \
+ libssl-dev \
+ ninja-build \
+ ccache \
+ clang-format-13
+```
+
+**macOS:**
+
+```bash
+xcode-select --install
+brew install cmake ninja ccache openssl clang-format
+```
+
+**Windows:**
+
+1. Install [Visual Studio 2022](https://visualstudio.microsoft.com/) with the **Desktop development with C++** workload
+2. Install [CMake](https://cmake.org/download/) β₯ 3.21
+3. Install [Git for Windows](https://git-scm.com/download/win)
+4. Install [Python 3](https://www.python.org/downloads/windows/)
+
+---
+
+## Cloning and Building
```bash
-# Clone
+# Clone the repository
git clone https://github.com/flamingo-stack/osquery.git
cd osquery
-# Configure (Debug build for development)
-cmake -S . -B build \
- -G Ninja \
+# Initialize submodules
+git submodule update --init --recursive
+
+# Create build directory (always build out-of-source)
+mkdir build && cd build
+
+# Configure for development (Debug mode + compile_commands.json)
+cmake .. \
+ -DCMAKE_C_COMPILER=clang \
+ -DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_BUILD_TYPE=Debug \
- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
- -DOSQUERY_BUILD_TESTS=ON
+ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
# Build
-cmake --build build --parallel $(nproc)
+cmake --build . --parallel $(nproc)
-# Run
-./build/osquery/osqueryi
+# Symlink compile_commands.json for IDE/clangd support
+cd ..
+ln -s build/compile_commands.json compile_commands.json
```
-For full environment setup instructions see the [Development Documentation](./docs/development/README.md).
+### Useful CMake Flags for Development
+
+| Flag | Description |
+|------|-------------|
+| `-DCMAKE_BUILD_TYPE=Debug` | Include debug symbols |
+| `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` | Generate `compile_commands.json` for IDE intelligence |
+| `-DOSQUERY_DISABLE_DATABASE=ON` | Skip RocksDB build (faster for table development) |
+| `-DCMAKE_C_COMPILER_LAUNCHER=ccache` | Enable ccache for faster incremental builds |
+| `-DCMAKE_CXX_COMPILER_LAUNCHER=ccache` | Enable ccache for C++ compilation |
---
-## Code Style and Conventions
+## Project Structure
-### C++ Standards
+```text
+osquery/
+βββ osquery/ # Core osquery C++ source (C++17)
+β βββ core/ # Runtime lifecycle, flags, watchdog
+β βββ sql/ # SQL engine and virtual table layer
+β βββ config/ # Configuration and query packs
+β βββ database/ # RocksDB and ephemeral backends
+β βββ events/ # Event publisher/subscriber system
+β βββ extensions/ # Thrift-based extension framework
+β βββ distributed/ # Distributed query engine
+β βββ logger/ # Logging and query metadata
+β βββ remote/ # HTTP client for TLS endpoints
+βββ openframe/ # OpenFrame-specific extensions (C++)
+β βββ openframe_authorization_manager.*
+β βββ openframe_encryption_service.*
+β βββ openframe_token_extractor.*
+β βββ openframe_token_refresher.*
+βββ plugins/ # Config, logger, database, distributed plugins
+βββ libraries/ # Vendored third-party libraries
+βββ tools/ # Code generation and CI scripts
+βββ external/ # Extension SDK examples
+βββ tests/ # Integration tests
+```
+
+---
-- Use **C++17** features where appropriate
-- Follow the existing code style in each file you modify
-- All new code must pass `clang-format` with the repository's `.clang-format` config
+## Code Style
-### Formatting
+### C++ Standards
-osquery enforces `clang-format`. Run it before every commit:
+- The codebase uses **C++17**
+- Follow the existing code style in the file you are editing
+- Use `clang-format` to format all C++ files before submitting
```bash
-# Format a single file
-clang-format -i path/to/your/file.cpp
+# Format a file in-place
+clang-format -i openframe/openframe_encryption_service.cpp
-# Format all changed files (compared to main branch)
-git diff --name-only main | grep -E '\.(cpp|h)$' | xargs clang-format -i
-
-# Check without modifying
-clang-format --dry-run --Werror path/to/your/file.cpp
+# Check formatting without modifying
+clang-format --dry-run --Werror openframe/openframe_encryption_service.cpp
```
### Naming Conventions
-| Item | Convention | Example |
-|---|---|---|
-| Classes | `PascalCase` | `EventSubscriberPlugin` |
-| Methods | `camelCase` | `generateRows()` |
-| Member variables | `snake_case_` (trailing underscore) | `running_` |
-| Constants | `kPascalCase` | `kSQLOpcodes` |
-| Macros | `UPPER_SNAKE_CASE` | `DECLARE_FLAG` |
-| Namespaces | `snake_case` | `osquery` |
-| Files | `snake_case.cpp` / `snake_case.h` | `event_subscriber.cpp` |
+| Construct | Convention | Example |
+|-----------|-----------|---------|
+| Classes | PascalCase | `OpenframeEncryptionService` |
+| Methods | camelCase | `extractToken()` |
+| Variables | snake_case | `token_path` |
+| Constants | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
+| Files | snake_case | `openframe_token_extractor.cpp` |
-### Include Order
+### General Guidelines
-Follow this include order with blank lines between groups:
+- Write self-documenting code; add comments for non-obvious logic
+- Keep functions focused on a single responsibility
+- Prefer `const` and RAII patterns
+- Do not introduce new dependencies without discussion in the community Slack
+- Follow existing patterns in the module you are modifying
-```cpp
-// 1. Standard library
-#include
-#include
-#include
-
-// 2. Third-party libraries
-#include
-#include
-
-// 3. osquery headers
-#include "osquery/core/core.h"
-#include "osquery/sql/sql.h"
-
-// 4. Local headers (same directory)
-#include "my_local_header.h"
-```
+---
-### Code Organization
+## Adding New OpenFrame Source Files
-- Keep headers (`*.h`) minimal β forward declare where possible
-- Use the `osquery` namespace for all production code
-- Place tests in `tests/` subdirectories alongside the source
-- New virtual tables go in `osquery/tables//`
+When adding a new C++ source file to the `openframe/` directory:
----
+1. Create the `.h` and `.cpp` files
+2. Add the source to the relevant `CMakeLists.txt`:
-## Branch Naming
+```cmake
+target_sources(openframe_lib PRIVATE
+ openframe/openframe_new_component.cpp
+)
+```
-Always branch from the latest `main`:
+3. Re-run CMake and rebuild:
```bash
-git checkout main
-git pull origin main
-git checkout -b feature/my-new-feature
+cd build
+cmake ..
+cmake --build . --parallel $(nproc)
```
-| Type | Pattern | Example |
-|---|---|---|
-| Feature | `feature/` | `feature/bpf-socket-events` |
-| Bug fix | `fix/` | `fix/config-refresh-race` |
-| OpenFrame integration | `openframe/` | `openframe/token-refresh-retry` |
-| Documentation | `docs/` | `docs/virtual-table-guide` |
-| Refactor | `refactor/` | `refactor/sql-authorizer` |
-| Test | `test/` | `test/events-integration` |
-| Release | `release/v` | `release/v5.13.0` |
-
---
-## Commit Message Format
-
-```text
-():
-
-
+## Running Tests
-
-```
+```bash
+cd build
-### Types
-
-| Type | When to Use |
-|---|---|
-| `feat` | New feature or capability |
-| `fix` | Bug fix |
-| `docs` | Documentation changes only |
-| `style` | Code formatting, no logic change |
-| `refactor` | Code refactoring without behavior change |
-| `test` | Adding or fixing tests |
-| `perf` | Performance improvement |
-| `chore` | Build, CI, tooling changes |
-| `openframe` | OpenFrame platform-specific changes |
-
-### Scopes
-
-| Scope | Area |
-|---|---|
-| `core` | Core init and runtime |
-| `sql` | SQL engine and virtual tables |
-| `config` | Configuration and packs |
-| `events` | Eventing framework |
-| `logger` | Logging and observability |
-| `db` | Database and storage |
-| `distributed` | Distributed querying |
-| `extensions` | Extension IPC |
-| `http` | Remote HTTP client |
-| `openframe` | OpenFrame auth layer |
-| `tables` | Virtual table implementations |
-
-### Examples
+# Run all unit tests
+ctest --parallel $(nproc) --output-on-failure
-```text
-feat(events): add BPF socket event publisher for Linux
+# Run a specific test binary
+./osquery/osquery_tests --gtest_filter=ConfigTests.*
-Implements a new BPF-based publisher that captures socket connect/accept
-events and exposes them via the bpf_socket_events virtual table.
+# Run with verbose output
+./osquery/osquery_tests --gtest_filter="*" --gtest_verbose=all
```
-```text
-fix(openframe): handle token refresh failure with exponential backoff
+### Writing Tests
-When OpenframeTokenRefresher encounters a network error, it now retries
-with exponential backoff instead of immediately stopping the refresh loop.
-```
+Tests use **Google Test (gtest)**. When modifying security-sensitive code in `openframe/`, always add unit tests:
-```text
-test(config): add pack discovery query unit tests
+```cpp
+// Test that decryption fails on tampered ciphertext
+TEST(EncryptionServiceTest, TamperedCiphertextThrows) {
+ OpenframeEncryptionService svc("your-32-byte-secret-key-here!!");
+ EXPECT_THROW(svc.decrypt("tampered_base64_payload"), std::runtime_error);
+}
```
---
-## Testing
-
-Tests use **Google Test** and **Google Mock**. Always build with `-DOSQUERY_BUILD_TESTS=ON`:
-
-```bash
-cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DOSQUERY_BUILD_TESTS=ON
-cmake --build build --parallel $(nproc)
-
-# Run all tests
-cd build && ctest --output-on-failure
+## Security Guidelines
-# Run in parallel
-cd build && ctest --output-on-failure --parallel $(nproc)
+Security is a top priority for all contributions. Follow these rules strictly:
-# Run a specific suite
-cd build && ctest -R "osquery_sql_tests" --output-on-failure
-```
+- **Never log token values** at any severity level
+- **Never hardcode secrets** β use environment variable injection or a secrets manager
+- **Always validate file paths** before opening them
+- **Always join background threads** on shutdown
+- **Never disable TLS peer verification** in production code
+- Use `OpenframeAuthorizationManagerProvider` to access the authorization manager β direct construction is private by design
-### Test Categories
+### Code Review Security Checklist
-| Category | Location | Description |
-|---|---|---|
-| Unit Tests | `osquery/*/tests/` | Fast, isolated, no OS dependencies |
-| Integration Tests | `tests/integration/tables/` | Live table queries against the real OS |
-| Extension Tests | `osquery/extensions/tests/` | IPC and Thrift round-trips |
-| Plugin Tests | `plugins/*/tests/` | Logger, config, and database plugins |
+Before submitting a PR that touches `openframe/`, `osquery/remote/`, or authentication logic:
-When contributing a new virtual table, a corresponding integration test in `tests/integration/tables/` is expected.
+- [ ] No secrets or tokens appear in log output
+- [ ] Secret keys are not hardcoded in source or tests
+- [ ] Encryption errors throw exceptions and do NOT silently return empty strings
+- [ ] All file paths are validated before use
+- [ ] Background threads are properly joined on shutdown
+- [ ] No new unsafe SQL execution paths are introduced
+- [ ] TLS peer verification is not disabled
---
## Pull Request Process
-### Before Submitting
-
-- [ ] Branch is up-to-date with `main`
-- [ ] All tests pass: `cd build && ctest --output-on-failure`
-- [ ] Code is formatted: `clang-format --dry-run --Werror`
-- [ ] Copyright headers are present on new files
-- [ ] New virtual tables have integration tests in `tests/integration/tables/`
-- [ ] OpenFrame-specific changes include updated documentation
-- [ ] Discussed in OpenMSP Slack (for significant changes)
-
-### PR Title Format
+1. **Discuss first** β Open a thread in the [OpenMSP Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) before starting significant work
+2. **Branch naming** β Use descriptive branch names: `feature/openframe-token-rotation`, `fix/rocksdb-shutdown-hang`
+3. **Commit messages** β Write clear, imperative commit messages: `Add AES key rotation support to OpenframeEncryptionService`
+4. **Keep PRs focused** β One logical change per PR; avoid mixing refactors with feature work
+5. **Run tests** β Ensure `ctest` passes before submitting
+6. **Format code** β Run `clang-format` on all modified files
+7. **Update documentation** β If you change a public interface or behavior, update the relevant docs
-Use the same format as commit messages:
+### Commit Message Format
```text
-feat(sql): add query result caching for repeated virtual table scans
+:
+
+
```
-### PR Description Template
+Types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, `security`
-```markdown
-## Summary
-
+**Examples:**
-## Changes
-
+```text
+feat: add OpenframeTokenRefresher configurable interval
-## Testing
-
+fix: resolve RocksDB file lock during rapid daemon restarts
-## Platform Support
-
+security: enforce TLS peer verification in all remote HTTP calls
-## Checklist
-- [ ] Tests pass (ctest)
-- [ ] clang-format applied
-- [ ] Documentation updated (if applicable)
-- [ ] Discussed in OpenMSP Slack (if significant change)
+docs: update prerequisites with OpenSSL version requirement
```
---
-## Copyright Headers
+## Running Locally in Development Mode
-All new source files must include a copyright header:
+Use the in-memory database for rapid iteration to avoid RocksDB file locking:
-```cpp
-/**
- * Copyright (c) 2014-present, The osquery authors
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
+```bash
+./build/osquery/osqueryd \
+ --config_path=/tmp/dev_osquery.conf \
+ --ephemeral=true \
+ --disable_database=true \
+ --verbose
```
-The CI script `tools/ci/scripts/check_copyright_headers.py` enforces this on all pull requests.
-
---
-## Adding a New Virtual Table
+## Debugging
-1. Define the table schema in `osquery/tables//.table`
-2. Run the code generator:
+### LLDB (macOS / Linux)
```bash
-python3 tools/codegen/gentable.py osquery/tables//.table
+lldb ./build/osquery/osqueryi
+(lldb) breakpoint set --name OpenframeEncryptionService::decrypt
+(lldb) run --verbose
```
-3. Implement the `generate()` method in `.cpp`
-4. Register in the CMakefile for your category
-5. Add an integration test in `tests/integration/tables/.cpp`
-6. Test locally:
+### GDB (Linux)
```bash
-cmake --build build --target osqueryi
-./build/osquery/osqueryi
-osquery> SELECT * FROM ;
+gdb ./build/osquery/osqueryi
+(gdb) break OpenframeTokenExtractor::extractToken
+(gdb) run --verbose
```
---
-## Security Guidelines
-
-- **Never** hardcode secrets, credentials, or tokens in source code
-- **Never** log JWT token values, even at debug level
-- SQL inputs must pass through the SQLite authorizer β do not bypass it
-- AES-GCM nonces must be generated freshly (never reused for the same key)
-- TLS peer verification must **not** be disabled in production code
-- New config keys must include size/depth validation
-- Thread-shared state must use proper synchronization primitives
+## Environment Variables
-Report security vulnerabilities directly to the Flamingo team via the **OpenMSP Slack community** β do not open public GitHub Issues for security issues.
+| Variable | Purpose | Notes |
+|----------|---------|-------|
+| `CC` | C compiler path | e.g., `/usr/bin/clang-13` |
+| `CXX` | C++ compiler path | e.g., `/usr/bin/clang++-13` |
+| `CCACHE_DIR` | ccache storage directory | e.g., `$HOME/.ccache` |
+| `OPENFRAME_TOKEN_PATH` | Path to encrypted token file | For OpenFrame integration |
+| `OPENFRAME_SECRET_KEY` | AES-256 key for token decryption | Inject from secrets manager; never hardcode |
---
-## Reviewer Checklist
-
-When reviewing a PR:
-
-- [ ] Logic is correct and all error paths are handled
-- [ ] No secrets or credentials in source
-- [ ] SQL inputs are validated through the authorizer
-- [ ] Thread safety considered for shared state
-- [ ] Platform-specific code is properly guarded with `#ifdef`
-- [ ] Tests added for new functionality
-- [ ] No debug/temporary code left in
-- [ ] Commit messages follow format convention
-- [ ] Performance impact considered for hot paths (scheduler, SQL engine)
-
----
+## Getting Help
-## Code of Conduct
+All development discussions happen in the [OpenMSP Slack community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA). This is the fastest way to get answers, discuss architecture decisions, or ask about contribution guidelines.
-Be respectful, collaborative, and constructive. All contributors are expected to maintain a professional and welcoming environment in both Slack and code reviews.
+- **OpenMSP Community**: [https://www.openmsp.ai/](https://www.openmsp.ai/)
+- **Flamingo**: [https://flamingo.run](https://flamingo.run)
+- **OpenFrame**: [https://openframe.ai](https://openframe.ai)
---
diff --git a/README.md b/README.md
index a707452a43e..bd46c88681c 100644
--- a/README.md
+++ b/README.md
@@ -10,238 +10,240 @@
-# osquery β OpenFrame Edition
+# osquery β OpenFrame-Enhanced Distribution
-**osquery** is a cross-platform operating system instrumentation framework that exposes live system state and activity as relational data β enabling you to query your operating system using SQL.
+**osquery** is a cross-platform operating system instrumentation framework that exposes system state as relational data using **SQL**. This distribution extends the upstream osquery project with **OpenFrame**-specific authentication, token management, and AES-256-GCM encryption services β part of the [Flamingo](https://flamingo.run) / [OpenFrame](https://openframe.ai) platform for intelligent MSP automation.
-Built and extended by the [Flamingo / OpenFrame](https://openframe.ai) platform, this distribution integrates osquery's powerful SQL telemetry engine with OpenFrame's AI-driven MSP automation infrastructure. Every host becomes a **SQL-queryable telemetry node** β no proprietary log parsers, no fragile scripts, just standard SQL.
+Instead of parsing log files or writing custom scripts, you query the operating system like a database:
```sql
--- Which processes are listening on ports?
-SELECT pid, name, port, protocol FROM listening_ports JOIN processes USING (pid);
+SELECT name, pid, path FROM processes WHERE on_disk = 0;
+```
--- What Chrome extensions are installed?
-SELECT u.username, e.name, e.version, e.permissions
-FROM users u, chrome_extensions e
-WHERE e.uid = u.uid;
+```sql
+SELECT address, mac FROM interface_addresses;
+```
+
+```sql
+SELECT * FROM users WHERE uid = 0;
```
+---
+
+## Watch: Introduction to osquery
+
+[](https://www.youtube.com/watch?v=bRd3JCJZ1vc)
+
+---
+
## Features
-- **SQL Querying** β Query live OS data with standard SQL via an embedded, hardened SQLite engine
-- **300+ Virtual Tables** β Platform-specific tables across Linux, macOS, and Windows covering processes, sockets, packages, users, registry, hardware, and more
-- **Event Monitoring** β inotify, BPF, FSEvents, ETW, and OpenBSM events exposed as queryable tables
-- **Scheduled Query Packs** β Configuration-driven query scheduling with differential result tracking (only changed rows are logged)
-- **Distributed Fleet Queries** β Remote SQL orchestration across entire fleets via TLS
-- **Extension System** β Runtime plugin model via Apache Thrift IPC β add custom tables, loggers, and config plugins as external processes
-- **OpenFrame Auth Layer** β AES-256-GCM encrypted JWT token management (`OpenframeAuthorizationManager`, `OpenframeEncryptionService`, `OpenframeTokenRefresher`) for seamless integration with the Flamingo/OpenFrame MSP platform
-- **Cross-Platform** β Linux (x86\_64, aarch64), macOS (Intel + Apple Silicon), and Windows x86\_64
-- **Security-First** β SQLite authorizer allowlists only safe opcodes, Watcher/Worker process isolation, peer-verified TLS everywhere
+- **SQL-based OS querying** β Interact with 300+ virtual tables covering processes, files, users, network, and kernel state
+- **Cross-platform** β Runs on Linux, macOS, and Windows with a unified SQL interface
+- **Scheduled query packs** β Define queries that run on configurable schedules
+- **Event-driven tables** β Subscribe to OS events: file changes, process launches, network connections
+- **Distributed querying** β Push queries to an entire fleet from a central control plane over TLS
+- **Plugin extensions** β Add custom tables, loggers, and config sources via Thrift IPC without modifying the binary
+- **OpenFrame integration** β Secure bearer-token authentication with the OpenFrame/Flamingo platform
+- **AES-256-GCM encryption** β Built-in encrypted token storage and retrieval at rest
+- **Differential logging** β Only changed rows (added/removed) are logged by default, drastically reducing output volume
+- **Watchdog supervision** β Watcher/worker process separation for resilient daemon operation
+- **Pluggable persistence** β RocksDB for durability or in-memory ephemeral backend for lightweight use
---
-## Architecture
+## System Architecture
```mermaid
-graph TD
- CLI["osqueryi / osqueryd"] --> Core["Core Init And Runtime"]
+flowchart TD
+ OpenFrame["OpenFrame Auth Layer"] --> Core["Core Runtime And Lifecycle"]
Core --> Config["Configuration And Packs"]
Core --> SQL["SQL Engine And Virtual Tables"]
- Core --> Events["Eventing Framework"]
- Core --> Logging["Logging And Observability"]
- Core --> DB["Database And Storage Plugins"]
- Core --> Dist["Distributed Querying"]
- Core --> Ext["Extensions And IPC"]
- Core --> HTTP["Remote HTTP Client"]
- Core --> OF["OpenFrame Auth Layer"]
+ Core --> DB["Database Backend"]
+ Core --> Logging["Logging And Query Metadata"]
+ Core --> Events["Events Core And Subscriptions"]
+ Core --> Extensions["Extensions Framework"]
+ Core --> Distributed["Distributed Querying"]
+
Config --> SQL
Config --> Events
+ Config --> Logging
+
SQL --> Logging
+ SQL --> DB
+
Events --> DB
- Dist --> SQL
- Dist --> HTTP
- Ext --> SQL
- Ext --> DB
- OF --> HTTP
+ Events --> Logging
+
+ Distributed --> SQL
+ Distributed --> DB
+ Distributed --> Logging
+
+ Extensions --> SQL
+ Extensions --> Config
+ Extensions --> Distributed
```
-| Module | Location | Responsibility |
-|---|---|---|
-| Core Init And Runtime | `osquery/core/` | Process lifecycle, flags, watcher/worker model |
-| SQL Engine And Virtual Tables | `osquery/sql/` | SQLite engine, authorizer, virtual table binding |
-| Configuration And Packs | `osquery/config/` | Scheduled queries, packs, decorators |
-| Eventing Framework | `osquery/events/` | Publisher/subscriber event system |
-| Logging And Observability | `osquery/logger/` | Differential logging, JSON serialization |
-| Database And Storage Plugins | `osquery/database/` | RocksDB persistent + ephemeral in-memory stores |
-| Distributed Querying | `osquery/distributed/` | Remote fleet orchestration |
-| Extensions And IPC | `osquery/extensions/` | Apache Thrift-based runtime extensions |
-| Remote HTTP Client | `osquery/remote/` | Boost.Asio/Beast HTTPS with strict TLS |
-| OpenFrame Auth Layer | `openframe/` | JWT token management + AES-256-GCM encryption |
+### Architectural Layers
+
+| Layer | Responsibility |
+|-------|---------------|
+| **Core Runtime** | Bootstrapping, flags, lifecycle, watchdog, shutdown |
+| **SQL Engine** | Embedded SQLite, virtual table layer, query planning (300+ tables) |
+| **Configuration** | Packs, scheduling, discovery, dynamic updates |
+| **Database Backend** | Persistent RocksDB and ephemeral in-memory keyβvalue storage |
+| **Logging** | Differential result serialization and logger plugin emission |
+| **Events** | Real-time OS event ingestion exposed as SQL tables |
+| **Distributed** | Pull-based remote query retrieval and TLS result submission |
+| **Extensions** | Thrift IPC for external plugin injection |
+| **OpenFrame Auth** | Token lifecycle, AES-256-GCM encryption, background refresh |
---
## Technology Stack
| Layer | Technology |
-|---|---|
-| Language | C++17 |
-| Build System | CMake 3.21+ with Ninja |
-| SQL Engine | SQLite (embedded, in-memory) |
-| IPC | Apache Thrift (UNIX sockets / named pipes) |
-| Encryption | OpenSSL (AES-256-GCM) |
-| Networking | Boost.Asio + Boost.Beast |
-| Event Systems | inotify, BPF, FSEvents, ETW, OpenBSM |
-| Database | RocksDB (persistent), ephemeral in-memory |
-| Testing | Google Test + Google Mock |
+|-------|-----------|
+| **Language** | C++17 |
+| **Build System** | CMake β₯ 3.21 |
+| **SQL Engine** | SQLite (embedded) |
+| **Persistent Database** | RocksDB |
+| **IPC / Extensions** | Apache Thrift |
+| **Networking** | Boost.Asio + Boost.Beast |
+| **Encryption** | OpenSSL (AES-256-GCM) |
+| **Logging** | Google glog |
+| **Testing** | Google Test (gtest) |
+| **Flags** | Google gflags |
---
## Hardware Requirements
-| Tier | RAM | CPU Cores | Disk |
-|---|---|---|---|
-| **Minimum** | 24 GB | 6 cores | 50 GB |
-| **Recommended** | 32 GB | 12 cores | 100 GB |
-
-> Building from source is resource-intensive. The recommended configuration significantly reduces build times and prevents out-of-memory failures during compilation.
-
----
-
-## Supported Platforms
-
-| Platform | Architecture | Notes |
-|---|---|---|
-| Linux | x86\_64, aarch64 | Ubuntu 20.04+, RHEL 8+, Debian 11+ |
-| macOS | x86\_64, aarch64 | macOS 12+ (Intel + Apple Silicon) |
-| Windows | x86\_64 | Windows 10/11, Server 2019+ |
+| Component | Minimum | Recommended |
+|-----------|---------|-------------|
+| **RAM** | 24 GB | 32 GB |
+| **CPU Cores** | 6 cores | 12 cores |
+| **Disk Space** | 50 GB | 100 GB |
---
## Quick Start
-### 1. Install Prerequisites
+### Prerequisites
-**Linux (Debian/Ubuntu):**
-
-```bash
-sudo apt-get update
-sudo apt-get install -y \
- build-essential cmake ninja-build python3 python3-pip \
- git openssl libssl-dev clang-format ccache
-```
+- CMake β₯ 3.21
+- Clang β₯ 13 or GCC β₯ 10 (C++17 required)
+- Python 3 β₯ 3.6
+- OpenSSL β₯ 1.1.1 (for OpenFrame encryption)
+- Git
-**macOS:**
+Verify your environment:
```bash
-xcode-select --install
-brew install cmake ninja python3 openssl git ccache
+cmake --version
+clang --version
+python3 --version
+openssl version
```
-**Windows:**
-
-1. Install [Visual Studio 2022](https://visualstudio.microsoft.com/) with the **Desktop development with C++** workload
-2. Install [CMake 3.21+](https://cmake.org/download/), [Git](https://git-scm.com/download/win), [Python 3.8+](https://www.python.org/downloads/windows/)
-3. Download the CLI binary directly: [openframe-cli\_windows\_amd64.zip](https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_windows_amd64.zip)
-
-### 2. Clone and Build
+### Build from Source
```bash
-# Clone
+# 1. Clone the repository
git clone https://github.com/flamingo-stack/osquery.git
cd osquery
-# Configure (Linux/macOS)
-cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -G Ninja
+# 2. Create the build directory
+mkdir build && cd build
-# Configure (Windows)
-cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "Visual Studio 17 2022"
+# 3. Configure with CMake
+cmake .. \
+ -DCMAKE_C_COMPILER=clang \
+ -DCMAKE_CXX_COMPILER=clang++ \
+ -DCMAKE_BUILD_TYPE=Release
-# Build β uses all available CPU cores
-cmake --build build --parallel $(nproc)
+# 4. Build (uses all available CPU cores)
+cmake --build . --parallel $(nproc)
+
+# 5. Run the interactive shell
+./osquery/osqueryi
```
-### 3. Run Your First Query
+### Windows (AMD64)
-```bash
-./build/osquery/osqueryi
-```
+1. Download: [openframe-cli_windows_amd64.zip](https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_windows_amd64.zip)
+2. Extract the archive
+3. Run the installer following the same steps as other operating systems
+
+### Your First Query
-```text
-Using a virtual database. Need help, type '.help'
-osquery>
+```bash
+./osquery/osqueryi
```
```sql
-osquery> SELECT hostname, cpu_brand, physical_memory FROM system_info;
-osquery> SELECT pid, name, port, protocol FROM listening_ports LIMIT 10;
-osquery> SELECT uid, username, shell FROM users;
-osquery> .tables
+-- List running processes
+SELECT pid, name, path FROM processes LIMIT 10;
+
+-- Check listening network ports
+SELECT pid, port, protocol, address FROM listening_ports;
+
+-- List all available tables
+.tables
+
+-- Exit
+.exit
```
-### 4. Run as a Daemon
+### Run the Daemon (Continuous Monitoring)
```bash
-sudo mkdir -p /etc/osquery
-sudo tee /etc/osquery/osquery.conf <<'EOF'
-{
- "options": {
- "logger_plugin": "filesystem",
- "schedule_splay_percent": 10
- },
- "schedule": {
- "system_info": {
- "query": "SELECT hostname, cpu_brand, physical_memory FROM system_info;",
- "interval": 3600
- }
- }
-}
-EOF
-
-sudo ./build/osquery/osqueryd --config_path=/etc/osquery/osquery.conf
+./osquery/osqueryd --config_path=/etc/osquery/osquery.conf
```
---
-## OpenFrame Integration
+## OpenFrame Extensions
-This distribution extends osquery with a secure authentication and encryption layer for the [OpenFrame platform](https://www.flamingo.run/openframe):
+This distribution adds the following components on top of upstream osquery:
| Component | Description |
-|---|---|
-| `OpenframeAuthorizationManager` | Lifecycle-controlled JWT token singleton (non-copyable) |
-| `OpenframeAuthorizationManagerProvider` | Sole factory and owner of the token manager |
-| `OpenframeEncryptionService` | AES-256-GCM symmetric encryption via OpenSSL |
-| `OpenframeTokenExtractor` | Token acquisition from OpenFrame services |
-| `OpenframeTokenRefresher` | Background thread for seamless token renewal |
+|-----------|-------------|
+| `OpenframeAuthorizationManager` | Singleton manager for securely storing and serving the OpenFrame bearer token |
+| `OpenframeEncryptionService` | AES-256-GCM encryption/decryption service that secures tokens at rest |
+| `OpenframeTokenExtractor` | Reads and decrypts authentication tokens from an encrypted token file on disk |
+| `OpenframeTokenRefresher` | Background thread that periodically re-extracts and refreshes the authentication token |
+
+---
+
+## Two Execution Modes
-Obtain your OpenFrame credentials from your platform administrator. Token lifecycle is fully automated once configured. Refer to your environment configuration for connection details.
+| Mode | Binary | Description |
+|------|--------|-------------|
+| **Interactive Shell** | `osqueryi` | Ad-hoc SQL queries against the local system |
+| **Daemon** | `osqueryd` | Continuous scheduled query execution |
---
## Documentation
-π See the [Documentation](./docs/README.md) for comprehensive guides.
+π See the [Documentation](./docs/README.md) for comprehensive guides, architecture references, and development workflows.
-- [Introduction](./docs/getting-started/introduction.md) β What is osquery + OpenFrame?
-- [Prerequisites](./docs/getting-started/prerequisites.md) β System and software requirements
-- [Quick Start](./docs/getting-started/quick-start.md) β Clone, build, and run
-- [First Steps](./docs/getting-started/first-steps.md) β Explore tables, packs, FIM, extensions
-- [Architecture Overview](./docs/development/architecture/README.md) β Module deep-dives
-- [Local Development](./docs/development/setup/local-development.md) β Build configurations and debugging
-- [Contributing Guidelines](./docs/development/contributing/guidelines.md) β Code style and PR process
+- [Introduction](./docs/getting-started/introduction.md) β What is osquery and how does it work
+- [Prerequisites](./docs/getting-started/prerequisites.md) β System requirements and build tool setup
+- [Quick Start](./docs/getting-started/quick-start.md) β Build and run in minutes
+- [First Steps](./docs/getting-started/first-steps.md) β Explore tables, security queries, and OpenFrame integration
---
-## Community and Support
+## Community & Support
-> We do **not** use GitHub Issues or GitHub Discussions. All support and collaboration happens on the **OpenMSP Slack community**.
+This project is managed through the **OpenMSP Slack community** β GitHub Issues and Discussions are not used.
-| Resource | Link |
-|---|---|
-| π¬ OpenMSP Community Slack | [Join here](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) |
-| π OpenMSP Website | [https://www.openmsp.ai/](https://www.openmsp.ai/) |
-| π OpenFrame Platform | [https://openframe.ai](https://openframe.ai) |
-| 𦩠Flamingo | [https://flamingo.run](https://flamingo.run) |
+- **Slack**: [Join OpenMSP](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA)
+- **OpenMSP Platform**: [https://www.openmsp.ai/](https://www.openmsp.ai/)
+- **Flamingo**: [https://flamingo.run](https://flamingo.run)
+- **OpenFrame**: [https://openframe.ai](https://openframe.ai)
---
diff --git a/docs/README.md b/docs/README.md
index 19d2db24188..efca391b0b9 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,6 +1,6 @@
-# osquery β OpenFrame Edition Documentation
+# osquery (OpenFrame-Enhanced) β Documentation
-Welcome to the documentation for **osquery with OpenFrame** β the cross-platform OS instrumentation framework extended with AI-driven MSP automation by [Flamingo](https://flamingo.run) and [OpenFrame](https://openframe.ai).
+Welcome to the documentation for the OpenFrame-enhanced distribution of **osquery**, a cross-platform OS instrumentation framework that exposes system state as relational data using SQL. This distribution is part of the [Flamingo](https://flamingo.run) / [OpenFrame](https://openframe.ai) platform for intelligent MSP automation.
---
@@ -11,7 +11,6 @@ Welcome to the documentation for **osquery with OpenFrame** β the cross-platfo
- [Reference Architecture](#-reference-architecture)
- [Architecture Diagrams](#-architecture-diagrams)
- [Quick Links](#-quick-links)
-- [Community](#-community)
---
@@ -19,100 +18,115 @@ Welcome to the documentation for **osquery with OpenFrame** β the cross-platfo
New to osquery? Start here.
-| Guide | Description |
-|---|---|
-| [Introduction](./getting-started/introduction.md) | What is osquery with OpenFrame? Features and target audience |
-| [Prerequisites](./getting-started/prerequisites.md) | System requirements, supported platforms, required software |
-| [Quick Start](./getting-started/quick-start.md) | Clone, build, and run osquery in under 10 minutes |
-| [First Steps](./getting-started/first-steps.md) | Explore virtual tables, scheduled packs, FIM, extensions, and OpenFrame |
-
-**Recommended reading order:** Introduction β Prerequisites β Quick Start β First Steps
+| Document | Description |
+|----------|-------------|
+| [Introduction](./getting-started/introduction.md) | What is osquery, key features, OpenFrame extensions, and architecture overview |
+| [Prerequisites](./getting-started/prerequisites.md) | System requirements, required build tools, and environment verification |
+| [Quick Start](./getting-started/quick-start.md) | Clone, build, and run osquery in minutes |
+| [First Steps](./getting-started/first-steps.md) | Explore tables, run security queries, create query packs, and configure OpenFrame integration |
---
## π Development
-Guides for contributors and developers building on or extending osquery.
+Guides for contributors and developers working on the codebase.
-### Setup
+| Document | Description |
+|----------|-------------|
+| [Development Overview](./development/README.md) | Project structure, technology stack, and navigation index |
+| [Environment Setup](./development/setup/environment.md) | IDE configuration (CLion, VS Code), compiler setup, ccache, clang-format |
+| [Local Development](./development/setup/local-development.md) | Build modes, running locally, incremental builds, debugging with LLDB/GDB |
+| [Architecture Overview](./development/architecture/README.md) | High-level system design, component diagrams, data flow, OpenFrame auth pipeline |
+| [Security Best Practices](./development/security/README.md) | Auth patterns, AES-256-GCM encryption, secrets management, TLS configuration |
-| Guide | Description |
-|---|---|
-| [Environment Setup](./development/setup/environment.md) | IDE recommendations, clangd, ccache, editor extensions |
-| [Local Development](./development/setup/local-development.md) | Build configurations, debug flags, GDB/LLDB, VS Code debugging |
+---
-### Architecture
+## π Reference Architecture
-| Guide | Description |
-|---|---|
-| [Architecture Overview](./development/architecture/README.md) | High-level module breakdown, runtime lifecycle, design decisions |
+Detailed technical documentation for each core module, auto-generated from source code analysis.
-### Quality
+### Core Runtime
-| Guide | Description |
-|---|---|
-| [Testing Guide](./development/testing/README.md) | GTest/GMock structure, running tests, writing unit and integration tests |
-| [Security Best Practices](./development/security/README.md) | Auth patterns, AES-256-GCM, SQL authorizer, TLS, secrets management |
+| Document | Description |
+|----------|-------------|
+| [Core Runtime And Lifecycle](./reference/architecture/core-runtime-and-lifecycle/core-runtime-and-lifecycle.md) | Bootstrapping, flag system, process modes, watchdog model, shutdown coordination |
-### Contributing
+### Query Engine
-| Guide | Description |
-|---|---|
-| [Contributing Guidelines](./development/contributing/guidelines.md) | Code style, branch naming, commit format, PR process, virtual table creation |
+| Document | Description |
+|----------|-------------|
+| [SQL Engine And Virtual Tables](./reference/architecture/sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md) | Embedded SQLite, virtual table integration, constraint pushdown, query planning, security authorizer |
----
+### Configuration
-## π Reference Architecture
+| Document | Description |
+|----------|-------------|
+| [Configuration And Packs](./reference/architecture/configuration-and-packs/configuration-and-packs.md) | Query packs, scheduling, discovery logic, denylisting, hash-based change detection |
+| [Config Plugins](./reference/architecture/config-plugins/config-plugins.md) | FilesystemConfigPlugin, OptionsConfigParserPlugin, ViewsConfigParserPlugin, DecoratorsConfigParserPlugin |
-Deep technical documentation for each core subsystem β generated directly from source code analysis.
-
-| Module | Description |
-|---|---|
-| [Core Init And Runtime](./reference/architecture/core-init-and-runtime/core-init-and-runtime.md) | Process bootstrap, flags, watcher/worker model, watchdog |
-| [SQL Engine And Virtual Tables](./reference/architecture/sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md) | SQLite engine, authorizer, virtual table binding, constraint pushdown |
-| [Configuration And Packs](./reference/architecture/configuration-and-packs/configuration-and-packs.md) | Config loading, packs, schedulers, decorators, change detection |
-| [Eventing Framework And Subscriptions](./reference/architecture/eventing-framework-and-subscriptions/eventing-framework-and-subscriptions.md) | Publisher/subscriber system, inotify, BPF, FSEvents, ETW |
-| [Extensions And IPC](./reference/architecture/extensions-and-ipc/extensions-and-ipc.md) | Apache Thrift IPC, runtime plugin model, UUID routing |
-| [Distributed Querying](./reference/architecture/distributed-querying/distributed-querying.md) | Remote SQL orchestration, TLS transport, fleet denylisting |
-| [Remote HTTP Client](./reference/architecture/remote-http-client/remote-http-client.md) | Boost.Asio/Beast HTTPS client, TLS handshake, peer verification |
-| [Logging And Query Observability](./reference/architecture/logging-and-query-observability/logging-and-query-observability.md) | Differential result tracking, JSON serialization, pluggable backends |
-| [Database And Storage Plugins](./reference/architecture/database-and-storage-plugins/database-and-storage-plugins.md) | RocksDB persistent backend, ephemeral in-memory store, key-value interface |
-| [Filesystem And Path Utilities](./reference/architecture/filesystem-and-path-utilities/filesystem-and-path-utilities.md) | Cross-platform file abstraction, glob resolution, permission enforcement |
+### Storage
----
+| Document | Description |
+|----------|-------------|
+| [Database Backend](./reference/architecture/database-backend/database-backend.md) | RocksDB persistent backend, ephemeral in-memory backend, domain-based keyβvalue storage, schema migration |
-## πΊ Architecture Diagrams
+### Observability
-Visual Mermaid diagrams for each subsystem are available in:
+| Document | Description |
+|----------|-------------|
+| [Logging And Query Metadata](./reference/architecture/logging-and-query-metadata/logging-and-query-metadata.md) | QueryLogItem, DiffResults, differential vs snapshot logging, JSON serialization |
+| [Events Core And Subscriptions](./reference/architecture/events-core-and-subscriptions/events-core-and-subscriptions.md) | Publisher/subscriber event framework, event persistence, schedule-aware expiration |
+| [Osquery Shell Devtooling](./reference/architecture/osquery-shell-devtooling/osquery-shell-devtooling.md) | `osqueryi` interactive shell, meta commands, pretty-print formatting, CPU profiling |
-```text
-docs/diagrams/architecture/
-```
+### Distribution & Extensions
-Diagrams cover all major subsystems including the SQL engine, eventing framework, configuration pipeline, distributed querying, OpenFrame auth layer, and more. Open any `.mmd` file in a Mermaid-compatible viewer.
+| Document | Description |
+|----------|-------------|
+| [Distributed Querying](./reference/architecture/distributed-querying/distributed-querying.md) | Pull-based distributed queries, discovery gating, denylisting, result batching |
+| [Distributed TLS Plugin](./reference/architecture/distributed-tls-plugin/distributed-tls-plugin.md) | Secure HTTPS transport for distributed queries via `TLSDistributedPlugin` |
+| [Extensions Framework](./reference/architecture/extensions-framework/extensions-framework.md) | Thrift IPC, dynamic plugin injection, UUID-based routing, health monitoring |
+
+### Networking & Filesystem
+
+| Document | Description |
+|----------|-------------|
+| [Remote HTTP Client](./reference/architecture/remote-http-client/remote-http-client.md) | Boost.Asio + Boost.Beast HTTP client, TLS validation, timeout handling, proxy support |
+| [Filesystem And Fileops Core](./reference/architecture/filesystem-and-fileops-core/filesystem-and-fileops-core.md) | Cross-platform file abstraction, secure permission validation, globbing, portable stat |
---
-## π Quick Links
+## πΊ Architecture Diagrams
-| Resource | Link |
-|---|---|
-| [Project README](../README.md) | Main project overview, quick start, and features |
-| [Contributing Guide](../CONTRIBUTING.md) | How to contribute code, docs, and virtual tables |
-| [License](../LICENSE.md) | License information |
+Mermaid-format architecture diagrams are available under `docs/diagrams/architecture/`. Key diagrams include:
+
+| Diagram | Description |
+|---------|-------------|
+| `docs/diagrams/architecture/core-runtime-and-lifecycle.mmd` | Core runtime lifecycle flow |
+| `docs/diagrams/architecture/sql-engine-and-virtual-tables.mmd` | SQL engine and virtual table layer |
+| `docs/diagrams/architecture/extensions-framework.mmd` | Extensions IPC and lifecycle |
+| `docs/diagrams/architecture/events-core-and-subscriptions.mmd` | Event publisher/subscriber pipeline |
+| `docs/diagrams/architecture/distributed-querying.mmd` | Distributed query execution flow |
+| `docs/diagrams/architecture/distributed-tls-plugin.mmd` | TLS-secured distributed transport |
+| `docs/diagrams/architecture/database-backend.mmd` | Database backend architecture |
+| `docs/diagrams/architecture/configuration-and-packs.mmd` | Configuration and scheduling flow |
+| `docs/diagrams/architecture/config-plugins.mmd` | Config plugin chain |
+| `docs/diagrams/architecture/remote-http-client.mmd` | HTTP client TLS flow |
+| `docs/diagrams/architecture/filesystem-and-fileops-core.mmd` | Filesystem abstraction layer |
+| `docs/diagrams/architecture/logging-and-query-metadata.mmd` | Logging pipeline |
+| `docs/diagrams/architecture/osquery-shell-devtooling.mmd` | Interactive shell architecture |
---
-## π¬ Community
-
-> We do **not** use GitHub Issues or GitHub Discussions. All support and collaboration happens on **OpenMSP Slack**.
+## π Quick Links
| Resource | Link |
-|---|---|
-| OpenMSP Community Slack | [Join here](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) |
-| OpenMSP Website | [https://www.openmsp.ai/](https://www.openmsp.ai/) |
-| OpenFrame Platform | [https://openframe.ai](https://openframe.ai) |
-| Flamingo | [https://flamingo.run](https://flamingo.run) |
+|----------|------|
+| [Project README](../README.md) | Main project README with Quick Start |
+| [Contributing Guide](../CONTRIBUTING.md) | How to contribute, code style, PR process |
+| [OpenMSP Community Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) | Community support (primary channel) |
+| [OpenMSP Platform](https://www.openmsp.ai/) | OpenMSP community platform |
+| [Flamingo](https://flamingo.run) | Flamingo AI-powered MSP platform |
+| [OpenFrame](https://openframe.ai) | OpenFrame unified MSP tooling platform |
---
diff --git a/docs/development/README.md b/docs/development/README.md
index 83ce9e027c8..b4124b57c45 100644
--- a/docs/development/README.md
+++ b/docs/development/README.md
@@ -1,96 +1,106 @@
# Development Documentation
-Welcome to the osquery with OpenFrame development documentation. This section covers everything you need to build, run, test, and contribute to the project.
+Welcome to the osquery (OpenFrame-enhanced) development documentation. This section covers everything you need to understand, build, modify, and contribute to this project.
---
## Overview
-osquery is a C++ cross-platform OS instrumentation framework. The codebase is organized around a modular, plugin-driven architecture where every major subsystem is independently testable and extensible.
-
-The **OpenFrame** layer adds authentication and encryption components that integrate with the [Flamingo/OpenFrame MSP platform](https://openframe.ai).
+This osquery distribution extends the upstream open-source osquery framework with OpenFrame-specific authentication, token management, and AES-256-GCM encryption services. The codebase is written in **C++17** and built with **CMake**, targeting Linux, macOS, and Windows.
---
## Documentation Index
-| Guide | Description |
-|---|---|
-| [Environment Setup](setup/environment.md) | IDE recommendations, development tools, editor extensions |
-| [Local Development](setup/local-development.md) | Clone, build, run locally, debug configuration |
-| [Architecture Overview](architecture/README.md) | High-level architecture diagrams and core component descriptions |
-| [Security Best Practices](security/README.md) | Auth patterns, encryption, secrets management |
-| [Testing Guide](testing/README.md) | Test structure, running tests, writing new tests |
-| [Contributing Guidelines](contributing/guidelines.md) | Code style, branch naming, PR process, commit format |
+### Setup
----
+| Document | Description |
+|----------|-------------|
+| [Environment Setup](setup/environment.md) | IDE configuration, development tools, editor extensions |
+| [Local Development](setup/local-development.md) | Cloning, building, running locally, debug configuration |
-## Technology Stack
+### Architecture
-| Layer | Technology |
-|---|---|
-| **Language** | C++17 |
-| **Build System** | CMake 3.21+ with Ninja |
-| **SQL Engine** | SQLite (embedded, in-memory) |
-| **IPC** | Apache Thrift (UNIX sockets / named pipes) |
-| **Encryption** | OpenSSL (AES-256-GCM via OpenFrame layer) |
-| **Networking** | Boost.Asio + Boost.Beast |
-| **Event Systems** | inotify (Linux), FSEvents (macOS), ETW (Windows), BPF (Linux) |
-| **Database** | RocksDB (persistent), ephemeral in-memory store |
-| **Code Generation** | Python scripts for table schema, API, and amalgamation |
-| **Testing** | Google Test + Google Mock |
+| Document | Description |
+|----------|-------------|
+| [Architecture Overview](architecture/README.md) | High-level system design, component diagrams, data flow |
+
+### Security
+
+| Document | Description |
+|----------|-------------|
+| [Security Best Practices](security/README.md) | Auth patterns, encryption, secrets management, vulnerability mitigations |
+
+### Testing
+
+| Document | Description |
+|----------|-------------|
+| [Testing Overview](testing/README.md) | Test structure, running tests, writing new tests, coverage |
+
+### Contributing
+
+| Document | Description |
+|----------|-------------|
+| [Contributing Guidelines](contributing/guidelines.md) | Code style, branch naming, PR process, commit format |
---
-## Repository Structure
+## Project Structure
```text
osquery/
-βββ osquery/ # Core C++ source β SQL, eventing, config, logging
-β βββ core/ # Initialization, flags, watcher/worker model
-β βββ sql/ # SQLite engine, virtual tables, authorizer
-β βββ config/ # Configuration loading, packs, parsers
-β βββ events/ # Eventing framework (publishers/subscribers)
-β βββ database/ # Storage backend abstraction (RocksDB, ephemeral)
-β βββ distributed/ # Distributed query orchestration
-β βββ extensions/ # Thrift-based extension/IPC framework
-β βββ remote/ # HTTP client, TLS transport
-β βββ logger/ # Logging plugins and observability
-β βββ tables/ # Virtual table implementations
-βββ openframe/ # OpenFrame authentication and encryption layer
-βββ plugins/ # Logger, config, database, and distributed plugins
-βββ libraries/ # CMake-managed third-party dependencies
-βββ tools/ # Codegen scripts, CI tools, formatting
-βββ tests/ # Integration test suite
-βββ external/ # Extension examples
+βββ osquery/ # Core osquery source (C++17)
+β βββ core/ # Runtime lifecycle, flags, watchdog
+β βββ sql/ # SQL engine and virtual table layer
+β βββ config/ # Configuration and query packs
+β βββ database/ # RocksDB and ephemeral backends
+β βββ events/ # Event publisher/subscriber system
+β βββ extensions/ # Thrift-based extension framework
+β βββ distributed/ # Distributed query engine
+β βββ logger/ # Logging and query metadata
+β βββ remote/ # HTTP client for TLS endpoints
+βββ openframe/ # OpenFrame-specific extensions (C++)
+β βββ openframe_authorization_manager.*
+β βββ openframe_encryption_service.*
+β βββ openframe_token_extractor.*
+β βββ openframe_token_refresher.*
+βββ plugins/ # Config, logger, database plugins
+βββ libraries/ # Vendored third-party libraries (CMake)
+βββ tools/ # Code generation, CI scripts
+βββ external/ # Extension SDK examples
+βββ tests/ # Integration tests
```
---
-## Quick Commands
+## Technology Stack
-```bash
-# Configure build
-cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo
+| Layer | Technology |
+|-------|-----------|
+| **Language** | C++17 |
+| **Build System** | CMake β₯ 3.21 |
+| **SQL Engine** | SQLite (embedded) |
+| **Persistent Database** | RocksDB |
+| **IPC / Extensions** | Apache Thrift |
+| **Networking** | Boost.Asio + Boost.Beast |
+| **Encryption** | OpenSSL (AES-256-GCM) |
+| **Logging** | Google glog |
+| **Testing** | Google Test (gtest) |
+| **Flags** | Google gflags |
+| **Documentation Pipeline** | VoltAgent + Anthropic AI |
-# Build everything
-cmake --build build --parallel $(nproc)
+---
-# Run interactive shell
-./build/osquery/osqueryi
+## Quick Navigation
-# Run tests
-cmake --build build --target osquery_tests
-cd build && ctest --output-on-failure
-```
+- New to the codebase? Start with [Architecture Overview](architecture/README.md).
+- Setting up your machine? See [Environment Setup](setup/environment.md).
+- Ready to code? Follow [Local Development](setup/local-development.md).
+- Writing a fix or feature? Read [Contributing Guidelines](contributing/guidelines.md).
+- Security concern? See [Security Best Practices](security/README.md).
---
-## Getting Help
-
-All development discussions happen in the **OpenMSP Slack community**:
-
-- [Join OpenMSP Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA)
-- [https://www.openmsp.ai/](https://www.openmsp.ai/)
+## Community
-> We do not use GitHub Issues or GitHub Discussions. All support and collaboration is on Slack.
+All development discussions happen in the [OpenMSP Slack community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA). This project does not use GitHub Issues or GitHub Discussions.
diff --git a/docs/development/architecture/README.md b/docs/development/architecture/README.md
index a7b03cb1fce..db2125bf672 100644
--- a/docs/development/architecture/README.md
+++ b/docs/development/architecture/README.md
@@ -1,239 +1,234 @@
# Architecture Overview
-osquery is built as a modular, plugin-driven system. Each subsystem is independently composable, testable, and extensible. The codebase is written in C++17 and targets Linux, macOS, and Windows.
+This document describes the high-level architecture of osquery (OpenFrame-enhanced), including core components, data flow, and the OpenFrame authentication layer.
---
-## High-Level Architecture
+## System Architecture
+
+osquery is structured as a modular, plugin-driven runtime. All major subsystems communicate through a **Registry** β a pluggable dispatch mechanism. The **Core Runtime** bootstraps every subsystem in a defined order and coordinates their lifecycle.
```mermaid
-graph TD
- CLI["osqueryi / osqueryd"] --> Core["Core Init And Runtime"]
- Core --> Config["Configuration And Packs"]
+flowchart TD
+ Core["Core Runtime And Lifecycle"] --> Config["Configuration And Packs"]
Core --> SQL["SQL Engine And Virtual Tables"]
- Core --> Events["Eventing Framework"]
- Core --> Logging["Logging And Observability"]
- Core --> DB["Database And Storage Plugins"]
- Core --> Dist["Distributed Querying"]
- Core --> Ext["Extensions And IPC"]
- Core --> HTTP["Remote HTTP Client"]
- Core --> OF["OpenFrame Auth Layer"]
+ Core --> DB["Database Backend"]
+ Core --> Logging["Logging And Query Metadata"]
+ Core --> Events["Events Core And Subscriptions"]
+ Core --> Extensions["Extensions Framework"]
+ Core --> Distributed["Distributed Querying"]
+
Config --> SQL
Config --> Events
+ Config --> Logging
+
SQL --> Logging
+ SQL --> DB
+
Events --> DB
- Dist --> SQL
- Dist --> HTTP
- Ext --> SQL
- Ext --> DB
- OF --> HTTP
+ Events --> Logging
+
+ Distributed --> SQL
+ Distributed --> DB
+ Distributed --> Logging
+
+ Extensions --> SQL
+ Extensions --> Config
+ Extensions --> Distributed
+
+ OpenFrame["OpenFrame Auth Layer"] --> Core
+ OpenFrame --> Distributed
```
---
## Core Components
-| Module | Location | Description |
-|---|---|---|
-| **Core Init And Runtime** | `osquery/core/` | Process bootstrap, flags, watchdog, shutdown |
-| **SQL Engine And Virtual Tables** | `osquery/sql/` | SQLite engine, authorizer, virtual table binding |
-| **Configuration And Packs** | `osquery/config/` | Config loading, packs, parsers, scheduled queries |
-| **Eventing Framework** | `osquery/events/` | Pub/sub system for OS events (inotify, BPF, ETW) |
-| **Logging And Observability** | `osquery/logger/` | Differential logging, JSON serialization, logger plugins |
-| **Database And Storage Plugins** | `osquery/database/` | Key-value storage (RocksDB, ephemeral) |
-| **Distributed Querying** | `osquery/distributed/` | Remote SQL orchestration across fleets |
-| **Extensions And IPC** | `osquery/extensions/` | Apache Thrift-based extension framework |
-| **Remote HTTP Client** | `osquery/remote/` | Boost.Asio/Beast HTTPS client with TLS |
-| **OpenFrame Auth Layer** | `openframe/` | JWT token management, AES-256-GCM encryption |
-| **Virtual Tables** | `osquery/tables/` | 300+ OS-specific table implementations |
+| Module | Path | Responsibility |
+|--------|------|---------------|
+| **Core Runtime** | `osquery/core/` | Bootstrapping, flags, watchdog, lifecycle, signal handling |
+| **SQL Engine** | `osquery/sql/` | Embedded SQLite, virtual table layer, query planning |
+| **Configuration** | `osquery/config/` | Query packs, scheduling, discovery, denylisting |
+| **Database Backend** | `osquery/database/` | RocksDB persistence and ephemeral in-memory storage |
+| **Logging** | `osquery/logger/` | Result diffing, QueryLogItem, serialization, logger plugins |
+| **Events** | `osquery/events/` | Publisher/subscriber system, event persistence |
+| **Extensions** | `osquery/extensions/` | Thrift IPC, extension registration, health monitoring |
+| **Distributed** | `osquery/distributed/` | Remote query pull, execution, result submission |
+| **Remote HTTP** | `osquery/remote/` | Boost.Asio/Beast HTTP client for TLS endpoints |
+| **OpenFrame Auth** | `openframe/` | Token management, AES-256-GCM encryption, background refresh |
---
-## Runtime Lifecycle
+## Query Execution Flow
```mermaid
sequenceDiagram
- participant Main
- participant Initializer
- participant Registry
- participant Config
- participant Extensions
- participant Events
-
- Main->>Initializer: Construct(argc, argv)
- Initializer->>Initializer: Parse flags
- Initializer->>Registry: registryAndPluginInit()
- Initializer->>Extensions: startExtensionManager()
- Initializer->>Config: load()
- Initializer->>Events: attachEvents()
- Initializer->>Initializer: start()
+ participant Sched as "Scheduler"
+ participant SQL as "SQL Engine"
+ participant VT as "Virtual Tables"
+ participant DB as "Database Backend"
+ participant Log as "Logger Plugin"
+
+ Sched->>SQL: Submit SQL query
+ SQL->>VT: Execute xFilter / xNext
+ VT-->>SQL: Return rows
+ SQL->>DB: getPreviousQueryResults()
+ DB-->>SQL: Previous rows
+ SQL->>SQL: Compute DiffResults (added/removed)
+ SQL->>Log: Emit QueryLogItem
+ SQL->>DB: saveQueryResults()
```
-osquery can operate in four runtime modes:
-
-| Mode | Binary | Description |
-|---|---|---|
-| **Interactive Shell** | `osqueryi` | REPL for ad-hoc SQL queries |
-| **Daemon** | `osqueryd` | Background daemon with scheduled queries |
-| **Watcher** | Internal | Supervisor process that monitors the worker |
-| **Extension** | External | External plugin process communicating via Thrift |
-
---
-## SQL Engine and Virtual Tables
+## Event Pipeline
-The heart of osquery is its SQL engine β an in-memory SQLite instance hardened with a strict authorizer.
+Event-based tables (file events, process events, network events) use a publish/subscribe model:
```mermaid
-graph TD
- Query["SQL Query"] --> SQLPlugin["SQLiteSQLPlugin"]
- SQLPlugin --> DBManager["SQLiteDBManager"]
- DBManager --> DBInst["SQLiteDBInstance"]
- DBInst --> SQLiteCore["In-Memory SQLite Engine"]
- SQLiteCore --> VTabModule["sqlite3_module"]
- VTabModule --> VirtualTable["VirtualTable Wrapper"]
- VirtualTable --> TablePlugin["TablePlugin"]
- TablePlugin --> OS["Operating System Data"]
+flowchart TD
+ Publisher["Event Publisher Plugin"] --> Subscription["Subscription"]
+ Subscription --> Subscriber["EventSubscriberPlugin"]
+ Subscriber --> DB["Database Backend"]
+ Subscriber --> VTable["Event Virtual Table"]
+ VTable --> Query["SELECT FROM event_table"]
+ Query --> Logging["Logger Plugin"]
```
-**Key properties:**
-- All queries run against an in-memory SQLite database
-- A strict authorizer allowlists only safe SQL opcodes
-- Virtual tables are attached dynamically from the registry
-- Constraint pushdown and projection optimization reduce OS calls
+### Event Model Key Facts
----
+- Publishers run in dedicated threads, collecting OS-level events
+- Subscribers transform events into rows and persist them to the database
+- SQL queries retrieve time-bounded results via `generateRows()`
+- Event expiration windows are schedule-aware
-## Eventing Framework
+---
-Event-driven monitoring is handled by a publish/subscribe system:
+## Distributed Query Flow
```mermaid
-graph TD
- Publisher["EventPublisher"] --> EventFactory["EventFactory"]
- Subscriber["EventSubscriber"] --> EventFactory
- EventFactory --> Callback["EventCallback"]
- Callback --> Storage["Database Storage"]
- SQL["SELECT from events tables"] --> Subscriber
+flowchart TD
+ Server["Remote Server"] --> TLSPlugin["Distributed TLS Plugin"]
+ TLSPlugin --> DistEngine["Distributed Querying"]
+ DistEngine --> SQL["SQL Engine"]
+ SQL --> Results["DistributedQueryResult"]
+ Results --> TLSPlugin
+ TLSPlugin --> Server
```
-| Platform | Event Technology |
-|---|---|
-| Linux | inotify, BPF, Audit netlink |
-| macOS | FSEvents, EndpointSecurity, OpenBSM |
-| Windows | ETW, USN Journal, Windows Event Log |
+Pull-based model β osquery polls the server for pending queries, executes them locally, and submits results back over TLS.
---
-## Configuration and Scheduling
+## Extensions Framework
+
+Extensions allow third-party processes to register new tables, config providers, and loggers without modifying the osquery binary:
```mermaid
-graph TD
- Source["Config Source"] --> ConfigCore["Config Singleton"]
- ConfigCore --> Parsers["ConfigParserPlugins"]
- Parsers --> Schedule["Scheduled Queries"]
- Schedule --> Scheduler["Query Scheduler"]
- Scheduler --> SQL["SQL Engine"]
- SQL --> Logging["Logging And Observability"]
+flowchart TD
+ Core["osquery Core"] --> Manager["Extension Manager"]
+ Manager --> Registry["RegistryFactory"]
+ ExtA["Extension Process A"] -->|"registerExtension()"| Manager
+ ExtB["Extension Process B"] -->|"registerExtension()"| Manager
+ Core -->|"callExtension()"| ExtA
+ Core -->|"callExtension()"| ExtB
```
-Configuration sources:
-- **FilesystemConfigPlugin** β local JSON file with `.d/` fragment support
-- **TLS Config Plugin** β remote configuration over HTTPS
-- **Extension Config Plugin** β configuration provided by an extension process
+Communication uses **Apache Thrift** over UNIX domain sockets (Linux/macOS) or named pipes (Windows).
---
## OpenFrame Authentication Layer
-The `openframe/` directory contains the Flamingo/OpenFrame integration:
+The OpenFrame extensions add a secure authentication pipeline:
```mermaid
-graph LR
- Provider["AuthorizationManagerProvider"] --> Manager["AuthorizationManager"]
- Extractor["TokenExtractor"] --> Manager
- Refresher["TokenRefresher"] --> Extractor
- Manager --> Token["JWT Bearer Token"]
- Token --> HTTP["Remote HTTP Client"]
- EncSvc["EncryptionService"] --> OpenSSL["OpenSSL AES-256-GCM"]
+flowchart LR
+ TokenFile["Encrypted Token File\n/etc/openframe/token.enc"] --> Extractor["OpenframeTokenExtractor"]
+ EncSvc["OpenframeEncryptionService\nAES-256-GCM"] --> Extractor
+ Extractor --> Refresher["OpenframeTokenRefresher\n(background thread)"]
+ Refresher --> Manager["OpenframeAuthorizationManager\n(singleton)"]
+ Manager --> OutboundReq["Authenticated HTTP Requests"]
```
| Component | Responsibility |
-|---|---|
-| `OpenframeAuthorizationManager` | Singleton token store with provider-controlled lifecycle |
-| `OpenframeAuthorizationManagerProvider` | Sole factory for the token manager |
-| `OpenframeEncryptionService` | AES-256-GCM decryption via OpenSSL |
-| `OpenframeTokenExtractor` | Fetches tokens from OpenFrame services |
-| `OpenframeTokenRefresher` | Background thread for token renewal |
-
----
+|-----------|---------------|
+| `OpenframeEncryptionService` | AES-256-GCM decryption with OpenSSL, Base64 decode |
+| `OpenframeTokenExtractor` | Reads encrypted token file, returns plaintext token |
+| `OpenframeTokenRefresher` | Background thread that periodically calls `extractToken()` |
+| `OpenframeAuthorizationManager` | Singleton that stores and serves the current bearer token |
+| `OpenframeAuthorizationManagerProvider` | Only class permitted to construct the manager (friend pattern) |
-## Extension System
-
-Extensions communicate with osquery core via Apache Thrift over UNIX domain sockets (Linux/macOS) or named pipes (Windows):
+### Token Lifecycle
```mermaid
-graph LR
- Core["osquery Core"] --> Manager["Extension Manager"]
- Manager --> Registry["RegistryFactory"]
- ExtProc["Extension Process"] --> Manager
- Manager --> ExtProc
+flowchart TD
+ Start["Process Startup"] --> Init["OpenframeTokenExtractor initialized"]
+ Init --> Extract["extractToken() β read + decrypt file"]
+ Extract --> Store["AuthorizationManager.updateToken()"]
+ Store --> Active["Token active β used in HTTP headers"]
+ Active --> Refresh["OpenframeTokenRefresher wakes up (interval)"]
+ Refresh --> Extract
```
-Extensions can provide:
-- Custom virtual tables
-- Logger plugins
-- Config plugins
-- Distributed plugins
+---
+
+## Database Domains
+
+The Database Backend organizes all persistent state into well-known domains:
+
+| Domain | Used By |
+|--------|---------|
+| `configurations` | Configuration And Packs |
+| `queries` | Query state diffing |
+| `events` | Events Core |
+| `logs` | Logger plugins |
+| `carves` | File carver |
+| `distributed` | Distributed Querying |
+| `query_performance` | Performance tracking |
---
-## Data Flow: Query Execution to Log
+## Process Modes
-```mermaid
-sequenceDiagram
- participant Scheduler
- participant SQL as SQL Engine
- participant DB as Database
- participant Logger
-
- Scheduler->>SQL: Execute scheduled query
- SQL->>SQL: Run against virtual tables
- SQL-->>Scheduler: QueryData (current results)
- Scheduler->>DB: Load previous results
- DB-->>Scheduler: Previous QueryData
- Scheduler->>Scheduler: Compute DiffResults
- Scheduler->>Logger: logQueryLogItem(diff)
- Logger->>Logger: Serialize to JSON
- Logger-->>Logger: Forward to backend sink
-```
+osquery runs in several distinct modes:
+
+| Mode | Binary | Description |
+|------|--------|-------------|
+| **Shell** | `osqueryi` | Interactive SQL shell for ad-hoc queries |
+| **Daemon** | `osqueryd` | Scheduled query execution in background |
+| **Watcher** | (internal) | Supervises worker process and restarts on failure |
+| **Worker** | (internal) | Actual query execution, spawned by watcher |
+| **Extension** | custom binary | External process registering new capabilities |
---
## Key Design Decisions
-| Decision | Rationale |
-|---|---|
-| **In-memory SQLite** | Zero persistent SQL state; each query is a fresh execution |
-| **Plugin/Registry pattern** | All major subsystems (loggers, config, tables) are hot-swappable |
-| **Watcher/Worker isolation** | Worker crashes don't bring down the watchdog supervisor |
-| **Thrift for extensions** | Language-agnostic, versioned, cross-platform RPC |
-| **Differential logging** | Only changed rows are logged, dramatically reducing volume |
-| **AES-256-GCM encryption** | OpenFrame credentials protected with authenticated encryption |
+1. **Registry-based plugins** β All major subsystems (SQL, config, logger, database, distributed) are pluggable via the Registry pattern, enabling replacement without core changes.
+
+2. **Virtual table layer** β OS data is never stored unless queried; virtual tables are instantiated on demand, keeping memory usage low.
+
+3. **Differential logging** β Only changed rows (added/removed) are logged by default, reducing output volume significantly.
+
+4. **Out-of-process extensions** β Thrift IPC isolates extension crashes from the core process.
+
+5. **Watchdog supervision** β Watcher/worker separation ensures daemon resilience; a crashing worker is restarted automatically.
+
+6. **OpenFrame auth separation** β The authentication layer is implemented as a separate C++ module under `openframe/`, keeping it isolated from the core osquery codebase.
---
## Reference Documentation
-For deep dives into each module, see the reference architecture docs:
+For detailed per-module documentation, see the auto-generated reference architecture docs:
-- [Core Init And Runtime](./reference/architecture/core-init-and-runtime/core-init-and-runtime.md)
+- [Core Runtime And Lifecycle](./reference/architecture/core-runtime-and-lifecycle/core-runtime-and-lifecycle.md)
- [SQL Engine And Virtual Tables](./reference/architecture/sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md)
- [Configuration And Packs](./reference/architecture/configuration-and-packs/configuration-and-packs.md)
-- [Eventing Framework And Subscriptions](./reference/architecture/eventing-framework-and-subscriptions/eventing-framework-and-subscriptions.md)
-- [Extensions And IPC](./reference/architecture/extensions-and-ipc/extensions-and-ipc.md)
+- [Database Backend](./reference/architecture/database-backend/database-backend.md)
+- [Events Core And Subscriptions](./reference/architecture/events-core-and-subscriptions/events-core-and-subscriptions.md)
+- [Extensions Framework](./reference/architecture/extensions-framework/extensions-framework.md)
- [Distributed Querying](./reference/architecture/distributed-querying/distributed-querying.md)
+- [Logging And Query Metadata](./reference/architecture/logging-and-query-metadata/logging-and-query-metadata.md)
- [Remote HTTP Client](./reference/architecture/remote-http-client/remote-http-client.md)
-- [Logging And Query Observability](./reference/architecture/logging-and-query-observability/logging-and-query-observability.md)
-- [Database And Storage Plugins](./reference/architecture/database-and-storage-plugins/database-and-storage-plugins.md)
-- [Filesystem And Path Utilities](./reference/architecture/filesystem-and-path-utilities/filesystem-and-path-utilities.md)
diff --git a/docs/development/contributing/guidelines.md b/docs/development/contributing/guidelines.md
deleted file mode 100644
index de082c732cb..00000000000
--- a/docs/development/contributing/guidelines.md
+++ /dev/null
@@ -1,272 +0,0 @@
-# Contributing Guidelines
-
-Thank you for contributing to osquery with OpenFrame! This guide covers code style, branching, commit messages, and the pull request process.
-
----
-
-## Community First
-
-All collaboration happens on the **OpenMSP Slack community** β not GitHub Issues or GitHub Discussions.
-
-- π¬ **Join Slack**: [OpenMSP Community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA)
-- π **OpenMSP**: [https://www.openmsp.ai/](https://www.openmsp.ai/)
-
-Before starting significant work, please discuss your changes in the Slack community to align with the team's roadmap.
-
----
-
-## Code Style and Conventions
-
-### C++ Standards
-
-- Use **C++17** features where appropriate
-- Follow the existing code style in each file you modify
-- All new code must pass `clang-format` with the repository's `.clang-format` config
-
-### Formatting
-
-osquery enforces `clang-format`. Run it before every commit:
-
-```bash
-# Format a single file
-clang-format -i path/to/your/file.cpp
-
-# Format all changed files (compared to main branch)
-git diff --name-only main | grep -E '\.(cpp|h)$' | xargs clang-format -i
-
-# Check without modifying
-clang-format --dry-run --Werror path/to/your/file.cpp
-```
-
-### Naming Conventions
-
-| Item | Convention | Example |
-|---|---|---|
-| Classes | `PascalCase` | `EventSubscriberPlugin` |
-| Methods | `camelCase` | `generateRows()` |
-| Member variables | `snake_case_` (trailing underscore) | `running_` |
-| Constants | `kPascalCase` | `kSQLOpcodes` |
-| Macros | `UPPER_SNAKE_CASE` | `DECLARE_FLAG` |
-| Namespaces | `snake_case` | `osquery` |
-| Files | `snake_case.cpp` / `snake_case.h` | `event_subscriber.cpp` |
-
-### Code Organization
-
-- Keep headers (`*.h`) as minimal as possible β forward declare where possible
-- Use the `osquery` namespace for all production code
-- Place tests in `tests/` subdirectories alongside the source
-- New virtual tables go in `osquery/tables//`
-
-### Include Order
-
-Follow this include order, with blank lines between groups:
-
-```cpp
-// 1. Standard library
-#include
-#include
-#include
-
-// 2. Third-party libraries
-#include
-#include
-
-// 3. osquery headers
-#include "osquery/core/core.h"
-#include "osquery/sql/sql.h"
-
-// 4. Local headers (same directory)
-#include "my_local_header.h"
-```
-
----
-
-## Branch Naming
-
-| Type | Pattern | Example |
-|---|---|---|
-| Feature | `feature/` | `feature/bpf-socket-events` |
-| Bug fix | `fix/` | `fix/config-refresh-race` |
-| OpenFrame integration | `openframe/` | `openframe/token-refresh-retry` |
-| Documentation | `docs/` | `docs/virtual-table-guide` |
-| Refactor | `refactor/` | `refactor/sql-authorizer` |
-| Test | `test/` | `test/events-integration` |
-| Release | `release/v` | `release/v5.13.0` |
-
-Always branch from the latest `main`:
-
-```bash
-git checkout main
-git pull origin main
-git checkout -b feature/my-new-feature
-```
-
----
-
-## Commit Message Format
-
-Use the following format for all commits:
-
-```text
-():
-
-
-
-
-```
-
-### Types
-
-| Type | When to Use |
-|---|---|
-| `feat` | New feature or capability |
-| `fix` | Bug fix |
-| `docs` | Documentation changes only |
-| `style` | Code formatting, no logic change |
-| `refactor` | Code refactoring without behavior change |
-| `test` | Adding or fixing tests |
-| `perf` | Performance improvement |
-| `chore` | Build, CI, tooling changes |
-| `openframe` | OpenFrame platform-specific changes |
-
-### Scopes
-
-| Scope | Area |
-|---|---|
-| `core` | Core init and runtime |
-| `sql` | SQL engine and virtual tables |
-| `config` | Configuration and packs |
-| `events` | Eventing framework |
-| `logger` | Logging and observability |
-| `db` | Database and storage |
-| `distributed` | Distributed querying |
-| `extensions` | Extension IPC |
-| `http` | Remote HTTP client |
-| `openframe` | OpenFrame auth layer |
-| `tables` | Virtual table implementations |
-
-### Examples
-
-```text
-feat(events): add BPF socket event publisher for Linux
-
-Implements a new BPF-based publisher that captures socket connect/accept
-events and exposes them via the bpf_socket_events virtual table.
-
-Closes #1234
-```
-
-```text
-fix(openframe): handle token refresh failure with exponential backoff
-
-When OpenframeTokenRefresher encounters a network error, it now retries
-with exponential backoff instead of immediately stopping the refresh loop.
-```
-
-```text
-test(config): add pack discovery query unit tests
-
-Adds unit tests for the discovery query evaluation logic in Pack::shouldPackExecute()
-covering platform, version, and shard constraints.
-```
-
----
-
-## Pull Request Process
-
-### Before Submitting
-
-- [ ] Branch is up-to-date with `main`
-- [ ] All tests pass: `cd build && ctest --output-on-failure`
-- [ ] Code is formatted: `clang-format --dry-run --Werror`
-- [ ] Copyright headers are present on new files
-- [ ] New virtual tables have integration tests in `tests/integration/tables/`
-- [ ] OpenFrame-specific changes include updated documentation
-
-### PR Title
-
-Use the same format as commit messages:
-
-```text
-feat(sql): add query result caching for repeated virtual table scans
-```
-
-### PR Description Template
-
-```markdown
-## Summary
-
-
-## Changes
-
-
-## Testing
-
-
-## Platform Support
-
-
-## Checklist
-- [ ] Tests pass (ctest)
-- [ ] clang-format applied
-- [ ] Documentation updated (if applicable)
-- [ ] Discussed in OpenMSP Slack (if significant change)
-```
-
----
-
-## Copyright Headers
-
-All new source files must include a copyright header. Use the format already present in existing source files:
-
-```cpp
-/**
- * Copyright (c) 2014-present, The osquery authors
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-```
-
-The CI script `tools/ci/scripts/check_copyright_headers.py` enforces this on all pull requests.
-
----
-
-## Review Checklist for Reviewers
-
-When reviewing a PR:
-
-- [ ] Logic is correct and handles error paths
-- [ ] No secrets or credentials in source
-- [ ] SQL inputs validated (if applicable)
-- [ ] Thread safety considered for shared state
-- [ ] Platform-specific code properly guarded with `#ifdef`
-- [ ] Tests added for new functionality
-- [ ] No debug/temporary code left in
-- [ ] Commit messages follow format convention
-- [ ] Performance impact considered for hot paths (scheduler, SQL engine)
-
----
-
-## Adding a New Virtual Table
-
-1. Define the table schema in `osquery/tables//.table`
-2. Run the code generator:
- ```bash
- python3 tools/codegen/gentable.py osquery/tables//.table
- ```
-3. Implement the `generate()` method in `.cpp`
-4. Register in the CMakefile for your category
-5. Add an integration test in `tests/integration/tables/.cpp`
-6. Test locally:
- ```bash
- cmake --build build --target osqueryi
- ./build/osquery/osqueryi
- osquery> SELECT * FROM ;
- ```
-
----
-
-## Code of Conduct
-
-Be respectful, collaborative, and constructive. All contributors are expected to maintain a professional and welcoming environment in both Slack and code reviews.
diff --git a/docs/development/security/README.md b/docs/development/security/README.md
index 87ae6702cae..f3820920dff 100644
--- a/docs/development/security/README.md
+++ b/docs/development/security/README.md
@@ -1,239 +1,227 @@
# Security Best Practices
-This guide covers security patterns used in osquery with OpenFrame, including authentication, encryption, secrets management, input validation, and common vulnerability mitigations.
+This document covers authentication patterns, encryption, secrets management, input validation, and security testing guidelines for osquery (OpenFrame-enhanced).
---
## Authentication and Authorization
-### OpenFrame JWT Token Management
+### OpenFrame Token Authentication
-The OpenFrame layer uses a provider-controlled singleton pattern to manage JWT authentication tokens:
+The OpenFrame authentication system uses a **bearer token** model secured by AES-256-GCM encryption at rest.
+
+**Key principles:**
+
+- Tokens are never stored in plaintext on disk.
+- The encrypted token file is read by `OpenframeTokenExtractor`, which decrypts it using a secret key passed at construction time.
+- The plaintext token is held only in memory via the `OpenframeAuthorizationManager` singleton.
+- A background thread (`OpenframeTokenRefresher`) rotates the in-memory token periodically, limiting exposure if the in-memory token is somehow leaked.
```mermaid
-graph LR
- Provider["AuthorizationManagerProvider"] --> Manager["AuthorizationManager"]
- Extractor["TokenExtractor"] --> Manager
- Refresher["TokenRefresher"] --> Extractor
- Manager --> Token["Bearer JWT Token"]
- Token --> HTTP["Outbound HTTPS Requests"]
+flowchart LR
+ Disk["Encrypted Token File\n(AES-256-GCM at rest)"] --> Extractor["OpenframeTokenExtractor\n(read + decrypt)"]
+ SecretKey["Secret Key\n(env var / secrets manager)"] --> EncSvc["OpenframeEncryptionService"]
+ EncSvc --> Extractor
+ Extractor --> Manager["AuthorizationManager\n(in-memory only)"]
+ Manager --> Request["Outbound HTTP Request\nAuthorization: Bearer ..."]
```
-**Key principles:**
-
-- `OpenframeAuthorizationManager` is **non-copyable** (`boost::noncopyable`) β tokens cannot be accidentally duplicated
-- Only `OpenframeAuthorizationManagerProvider` can construct or destroy the manager (private constructor/destructor)
-- The `OpenframeTokenRefresher` runs in a dedicated background thread using `std::atomic` for lock-free lifecycle control
-- Token updates and reads are centralized through `updateToken()` and `getToken()`
+### Security Rules for Token Handling
-**Never:**
-- Store JWT tokens in plain text files or environment variables without appropriate OS-level access controls
-- Log token values, even at debug level
-- Pass tokens as command-line arguments
+- **Do NOT** log the token value at any severity level.
+- **Do NOT** print the secret key or token in error messages.
+- **Do NOT** store decrypted tokens in configuration files or environment variable dumps.
+- **ALWAYS** use `OpenframeAuthorizationManagerProvider` to access the manager β direct construction is private by design.
+- **ALWAYS** call `stop()` on `OpenframeTokenRefresher` before destroying it to avoid dangling threads.
---
## Encryption
-### AES-256-GCM via OpenSSL
-
-The `OpenframeEncryptionService` provides symmetric encryption using AES-256-GCM β an authenticated encryption scheme:
-
-```cpp
-// Initialize with a 256-bit secret key
-OpenframeEncryptionService enc("my-32-byte-secret-key-goes-here!");
-
-// Decrypt a Base64-encoded AES-256-GCM ciphertext
-std::string plaintext = enc.decrypt(ciphertext_base64);
-```
+### AES-256-GCM (OpenframeEncryptionService)
-**Encryption properties:**
+The `OpenframeEncryptionService` provides:
-| Property | Value |
-|---|---|
+| Parameter | Value |
+|-----------|-------|
| Algorithm | AES-256-GCM |
-| Key size | 32 bytes (256-bit) |
-| IV (nonce) size | 12 bytes (96-bit) |
-| Authentication tag | 16 bytes (128-bit) |
+| Key size | 256 bits (32 bytes) |
+| IV size | 96 bits (12 bytes) |
+| Auth tag | 128 bits (16 bytes) |
| Encoding | Base64 |
-**Security rules:**
-- The symmetric key must be exactly 32 bytes
-- GCM authentication tag is verified on every decryption β tampered ciphertext throws `std::runtime_error`
-- Never reuse nonces for the same key
-- Store keys using OS keystore mechanisms or secret management systems, not in source code
+**Authentication tag verification** is enforced by AES-GCM β any tampered ciphertext will cause decryption to fail with a `std::runtime_error`. This provides both **confidentiality and integrity**.
----
-
-## SQL Security β The Authorizer
-
-osquery's embedded SQLite engine includes a strict **authorizer** (`sqliteAuthorizer`) that allowlists only safe SQL operations:
+#### Correct Usage
-```mermaid
-graph TD
- Prepare["sqlite3_prepare_v2"] --> Authorizer["sqliteAuthorizer"]
- Authorizer -->|"Allowed"| Continue["Execute Statement"]
- Authorizer -->|"Denied"| Reject["SQLITE_DENY"]
+```cpp
+// Initialize with a 256-bit (32-byte) secret key
+OpenframeEncryptionService enc_service("your-32-byte-secret-key-here!!");
+
+try {
+ std::string plaintext = enc_service.decrypt(encrypted_payload_base64);
+ // Use plaintext; do NOT log it
+} catch (const std::runtime_error& e) {
+ LOG(ERROR) << "Token decryption failed: " << e.what();
+ // Do NOT include the ciphertext or key in the log message
+}
```
-**Explicitly allowlisted:**
-- `SELECT`, `READ` operations
-- Controlled `INSERT`, `UPDATE`, `DELETE` (virtual tables only)
-- Virtual table creation and drop
-- Limited `PRAGMA` commands
+#### Security Prohibitions
-**Explicitly denied:**
-- `SQLITE_ATTACH` β cannot attach external database files
-- Any non-allowlisted opcode
+```cpp
+// β NEVER do this β logs the plaintext token
+LOG(INFO) << "Token: " << plaintext;
+
+// β NEVER do this β hardcodes the secret key in source code
+OpenframeEncryptionService enc("hardcoded-secret-key-bad!!!!!");
-This prevents osquery from being abused to read arbitrary files via SQLite's `ATTACH` mechanism or execute unsafe operations.
+// β
Correct β inject from a secure source
+std::string secret = getFromSecretsManager();
+OpenframeEncryptionService enc(secret);
+```
---
-## Input Validation
+## Secrets Management
-### SQL Query Validation
+### Rules
-All SQL submitted through the distributed querying or config channels is:
-1. Parsed by the SQLite authorizer before execution
-2. Validated against the virtual table schema
-3. Size-limited by configuration constraints
+1. **Never hardcode secrets** β Secret keys, API tokens, and encryption keys must never appear in source code, configuration files, or commit history.
-### Configuration Validation
+2. **Use environment variables or a secrets manager** β Provide the OpenFrame secret key via:
+ - A secrets manager (HashiCorp Vault, AWS Secrets Manager, etc.)
+ - A secure environment variable injected at process start time
+ - A protected file with `chmod 600` ownership-restricted to the osquery process user
-The `Config` singleton enforces:
-- JSON max depth limits
-- JSON max document size limits
-- Comment stripping (non-standard JSON is rejected)
-- Hash-based change detection to prevent replay attacks
+3. **Restrict file permissions** on token files:
-### Extension Registration
+```bash
+# Token file must be readable only by the osquery service user
+sudo chown osquery:osquery /etc/openframe/token.enc
+sudo chmod 600 /etc/openframe/token.enc
+```
-Extension processes are validated during registration:
-- SDK version compatibility is enforced
-- Duplicate extension names are rejected
-- Route UUIDs are generated server-side (not client-controlled)
+4. **Rotate tokens regularly** β The `OpenframeTokenRefresher` background thread handles periodic rotation of the in-memory token. Ensure your token files are also rotated at the platform level.
----
+5. **Audit secret access** β Log access to the token file path (not its content) to detect unauthorized access attempts.
-## Secrets Management
+---
-### Environment-Level Secrets
+## Input Validation and Sanitization
-Never embed secrets in:
-- Source code
-- CMake configuration
-- Build scripts
-- Log output
+### SQL Injection Prevention
-Use OS-level secrets management:
+osquery's SQL engine uses an **authorizer** (`sqliteAuthorizer`) that enforces a strict allowlist of SQL operations:
-| Platform | Recommended Tool |
-|---|---|
-| Linux | systemd credentials, HashiCorp Vault, AWS Secrets Manager |
-| macOS | Keychain, AWS Secrets Manager |
-| Windows | Windows Credential Manager, Azure Key Vault |
+| Allowed | Denied |
+|---------|--------|
+| `SELECT`, `READ` | `ATTACH DATABASE` |
+| `INSERT`, `UPDATE`, `DELETE` | Unauthorized `PRAGMA` calls |
+| `CREATE/DROP TABLE`, `CREATE/DROP VIEW` | File write operations |
+| `FUNCTION` calls | Anything not on the allowlist |
-### osquery Flag Files
+When writing extension tables or custom plugins, follow these guidelines:
-Sensitive flags (TLS certificates, enrollment secrets) should be stored in a flagfile with restricted permissions:
+```cpp
+// β
Validate all column constraint values before use
+if (context.constraints["pid"].existsAndMatches("1")) {
+ // safe to process
+}
-```bash
-# Create flagfile with restricted permissions
-sudo touch /etc/osquery/osquery.secret.flags
-sudo chmod 600 /etc/osquery/osquery.secret.flags
-sudo chown root:root /etc/osquery/osquery.secret.flags
-
-# Write sensitive flags
-echo "--tls_server_certs=/etc/osquery/server.pem" | sudo tee -a /etc/osquery/osquery.secret.flags
-echo "--enroll_secret_path=/etc/osquery/enroll.secret" | sudo tee -a /etc/osquery/osquery.secret.flags
+// β
Use parameterized operations, not string concatenation
+// β NEVER build SQL strings from user input
```
-Reference the flagfile:
+### Extension Plugin Input Validation
-```bash
-sudo ./osqueryd --flagfile=/etc/osquery/osquery.secret.flags
-```
+When implementing a `TablePlugin`:
+
+- Validate all incoming `QueryContext` constraints before acting on them.
+- Reject negative or out-of-range integer constraints.
+- Sanitize filesystem paths to prevent path traversal.
+- Limit result set sizes to prevent memory exhaustion.
---
-## TLS / HTTPS Communication
+## Network Security (TLS Configuration)
-### Remote HTTP Client Security
+The Remote HTTP Client (`osquery/remote/`) supports comprehensive TLS options:
-The `Remote HTTP Client` module (`osquery/remote/`) enforces:
-- TLS by default for all remote communication
-- Peer certificate verification
-- Configurable cipher suites
-- Custom CA certificate paths
-- Timeout enforcement (no hanging connections)
+| Option | Recommendation |
+|--------|---------------|
+| `always_verify_peer` | Set to `true` in production |
+| Custom CA path | Pin to your organization's CA bundle |
+| TLS version | Use TLS 1.2 or higher |
+| Client certificate | Use mutual TLS (mTLS) for sensitive endpoints |
-```text
-Client::Options options;
-options.ssl_connection(true)
- .verify_peer(true)
- .ca_verify_path("/etc/ssl/certs/ca-certificates.crt")
- .timeout(30);
-```
+**Never** disable peer verification in production:
-**Never disable peer verification in production.** The `verify_peer` flag should only be `false` in isolated development environments.
+```bash
+# β Insecure β never use in production
+osqueryd --tls_server_certs="" --disable_ciphers="..."
+
+# β
Secure β pin to your CA bundle
+osqueryd --tls_server_certs=/etc/ssl/openframe-ca.pem
+```
---
## Common Vulnerabilities and Mitigations
-| Vulnerability | Mitigation in osquery |
-|---|---|
-| **SQL Injection** | Authorizer blocks unsafe opcodes; only allowlisted operations execute |
-| **Credential Theft** | JWT tokens non-copyable, stored in singleton with restricted access |
-| **Ciphertext Tampering** | AES-256-GCM authentication tag verified on every decrypt |
-| **Privilege Escalation** | Watcher/Worker model isolates query execution from the supervisor |
-| **External DB Injection** | `SQLITE_ATTACH` explicitly denied by authorizer |
-| **Token Replay** | `OpenframeTokenRefresher` rotates tokens on a schedule |
-| **Extension Impersonation** | SDK version check and UUID server-assignment prevent spoofing |
-| **Resource Exhaustion** | Watchdog enforces CPU/memory limits and respawns workers |
-| **Config Tampering** | Hash-based change detection and JSON size/depth limits |
+| Vulnerability | Mitigation |
+|--------------|------------|
+| Token plaintext logged | Never log token values; review all log calls in auth code |
+| Hardcoded secrets in source | Use secrets manager / environment injection; enforce in code review |
+| Path traversal in token file path | Validate and sanitize all file paths before opening |
+| Memory exposure of decrypted token | Minimize lifetime of plaintext token; zero memory on deallocation where possible |
+| TOCTOU on token file | Read file atomically; hold exclusive lock during decrypt |
+| SQL injection via distributed queries | Rely on the SQLite authorizer; never execute raw user input without validation |
+| Extension process spoofing | Validate extension SDK version and UUID at registration |
---
-## Security Testing
+## Security Testing Guidelines
-### Running Security-Relevant Tests
+### Unit Tests for Security-Sensitive Code
-```bash
-# Build with tests enabled
-cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DOSQUERY_BUILD_TESTS=ON
-cmake --build build --parallel $(nproc)
-
-# Run all tests
-cd build && ctest --output-on-failure
+When writing or modifying `openframe/` components:
-# Run specific security-related tests
-cd build && ctest -R "tls" --output-on-failure
-cd build && ctest -R "config" --output-on-failure
-cd build && ctest -R "sql" --output-on-failure
+```cpp
+// Test that decryption fails on tampered ciphertext
+TEST(EncryptionServiceTest, TamperedCiphertextThrows) {
+ OpenframeEncryptionService svc("your-32-byte-secret-key-here!!");
+ EXPECT_THROW(svc.decrypt("tampered_base64_payload"), std::runtime_error);
+}
+
+// Test that empty token file path throws
+TEST(TokenExtractorTest, EmptyPathThrows) {
+ auto enc = std::make_shared("key...");
+ OpenframeTokenExtractor extractor(enc, "");
+ EXPECT_THROW(extractor.extractToken(), std::runtime_error);
+}
```
-### Code Review Checklist for Security
+### Code Review Checklist for Security PRs
-Before submitting any PR that touches security-sensitive code:
+Before merging any PR touching `openframe/`, `osquery/remote/`, or authentication logic:
-- [ ] No secrets or credentials hardcoded
-- [ ] All SQL inputs pass through the authorizer
-- [ ] AES-GCM nonces are generated freshly (not reused)
-- [ ] TLS peer verification is not disabled
-- [ ] Error paths do not leak sensitive information in logs
-- [ ] New extension APIs validate input size and type
-- [ ] Thread-shared state uses proper synchronization primitives
-- [ ] New config keys have size/depth validation
+- [ ] No secrets or tokens appear in log output.
+- [ ] Secret keys are not hardcoded in source or tests.
+- [ ] Encryption errors throw exceptions and do NOT silently return empty strings.
+- [ ] All file paths are validated before use.
+- [ ] Background threads are properly joined on shutdown.
+- [ ] No new unsafe SQL execution paths are introduced.
+- [ ] TLS peer verification is not disabled.
---
-## Reporting Security Issues
-
-Security vulnerabilities should be reported directly to the Flamingo team through the **OpenMSP Slack community**:
+## Environment Variables and Secrets at Runtime
-- π¬ [Join OpenMSP Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA)
-- π [https://www.openmsp.ai/](https://www.openmsp.ai/)
+| Variable | Handling |
+|----------|---------|
+| OpenFrame secret key | Inject via secrets manager; do NOT put in shell history |
+| Token file path | Configure in osquery flags; restrict file permissions to `600` |
+| TLS certificate paths | Store in `/etc/osquery/` with `640` permissions, `osquery` group |
-> Do not open public GitHub Issues for security vulnerabilities.
+> **Reminder:** This project uses the [OpenMSP Slack community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) for security discussions. For responsible disclosure, reach out there directly.
diff --git a/docs/development/setup/environment.md b/docs/development/setup/environment.md
index 882e48c34fb..965e8ef393d 100644
--- a/docs/development/setup/environment.md
+++ b/docs/development/setup/environment.md
@@ -1,200 +1,239 @@
# Development Environment Setup
-This guide covers recommended IDE configurations, development tools, editor extensions, and environment variables for contributing to osquery with OpenFrame.
+This guide covers how to configure your development environment for working on osquery (OpenFrame-enhanced), including IDE setup, recommended tools, and required extensions.
---
-## Recommended IDEs
+## Recommended IDE: CLion or VS Code
-### Visual Studio Code (All Platforms)
+### Option A β CLion (Recommended for C++)
-VS Code with the C++ extension pack is the recommended cross-platform IDE for osquery development.
+[CLion](https://www.jetbrains.com/clion/) provides native CMake integration and is the most productive IDE for this C++17 codebase.
-**Required Extensions:**
+**Setup steps:**
-| Extension | ID | Purpose |
-|---|---|---|
-| C/C++ | `ms-vscode.cpptools` | IntelliSense, debugging, syntax highlighting |
-| CMake Tools | `ms-vscode.cmake-tools` | CMake integration, build configuration |
-| CMake | `twxs.cmake` | CMake syntax highlighting |
-| clangd | `llvm-vs-code-extensions.vscode-clangd` | Fast code navigation, diagnostics |
+1. Install CLion (commercial license or free trial).
+2. Open the repository root directory β CLion auto-detects `CMakeLists.txt`.
+3. Configure the CMake profile:
+ - Navigate to **Settings β Build, Execution, Deployment β CMake**
+ - Add a profile: `Debug` with generator `Ninja` or `Unix Makefiles`
+ - Set CMake options:
-**Optional but Recommended:**
+```text
+-DCMAKE_C_COMPILER=clang
+-DCMAKE_CXX_COMPILER=clang++
+-DCMAKE_BUILD_TYPE=Debug
+```
-| Extension | ID | Purpose |
-|---|---|---|
-| GitLens | `eamodio.gitlens` | Enhanced Git history and annotations |
-| Clang-Format | `xaver.clang-format` | Auto-formatting on save |
-| Error Lens | `usernamehakki.error-lens` | Inline error display |
+4. Enable **clangd** for code intelligence under **Settings β Languages & Frameworks β C/C++ β Clangd**.
-**Install all at once:**
+---
-```bash
-code --install-extension ms-vscode.cpptools
-code --install-extension ms-vscode.cmake-tools
-code --install-extension twxs.cmake
-code --install-extension llvm-vs-code-extensions.vscode-clangd
-code --install-extension eamodio.gitlens
-```
+### Option B β Visual Studio Code
-**Recommended `.vscode/settings.json`:**
+VS Code works well with the following extensions installed:
+
+| Extension | ID | Purpose |
+|-----------|-----|---------|
+| **C/C++ Extension Pack** | `ms-vscode.cpptools-extension-pack` | C++ IntelliSense, debugging |
+| **CMake Tools** | `ms-vscode.cmake-tools` | CMake integration |
+| **clangd** | `llvm-vs-code-extensions.vscode-clangd` | Fast code intelligence via clang |
+| **CodeLLDB** | `vadimcn.vscode-lldb` | LLDB debugger integration |
+| **GitLens** | `eamodio.gitlens` | Enhanced Git integration |
+
+**VS Code workspace settings** (create `.vscode/settings.json`):
```json
{
+ "cmake.configureArgs": [
+ "-DCMAKE_C_COMPILER=clang",
+ "-DCMAKE_CXX_COMPILER=clang++"
+ ],
"cmake.buildDirectory": "${workspaceFolder}/build",
- "cmake.generator": "Ninja",
- "cmake.buildType": "Debug",
- "editor.formatOnSave": true,
"clangd.arguments": [
"--compile-commands-dir=${workspaceFolder}/build",
- "--header-insertion=iwyu",
+ "--background-index",
"--clang-tidy"
],
"C_Cpp.intelliSenseEngine": "disabled"
}
```
-> When using `clangd`, disable the built-in IntelliSense engine to avoid conflicts.
-
---
-### CLion (JetBrains)
+## Required Development Tools
+
+### Linux (Ubuntu/Debian)
+
+```bash
+sudo apt-get update && sudo apt-get install -y \
+ build-essential \
+ cmake \
+ clang-13 \
+ clang++-13 \
+ lld-13 \
+ python3 \
+ python3-pip \
+ git \
+ libssl-dev \
+ ninja-build \
+ ccache
+```
-CLion provides first-class CMake support. Open the project root and CLion will auto-detect the `CMakeLists.txt`.
+### macOS
-**Recommended Settings:**
+```bash
+# Install Xcode command-line tools
+xcode-select --install
-- Set the CMake build directory to `build/`
-- Enable `clang-format` in **Settings β Editor β Code Style β C/C++**
-- Use the built-in CMake tab for build configuration
+# Install Homebrew
+/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+
+# Install tools
+brew install cmake ninja ccache openssl
+```
+
+### Windows
+
+1. Install [Visual Studio 2022](https://visualstudio.microsoft.com/) with:
+ - **Desktop development with C++** workload
+ - **Windows 11 SDK**
+ - **LLVM/Clang compiler** (optional, but recommended)
+2. Install [CMake](https://cmake.org/download/) β₯ 3.21.
+3. Install [Git for Windows](https://git-scm.com/download/win).
+4. Install [Python 3](https://www.python.org/downloads/windows/).
---
-### Xcode (macOS Only)
+## Compiler Configuration
+
+osquery requires **C++17** support. The recommended compiler configuration:
-Generate an Xcode project from CMake:
+| Platform | Compiler | Version |
+|----------|---------|---------|
+| Linux | Clang | β₯ 13 |
+| macOS | Apple Clang | β₯ 13 (Xcode β₯ 13) |
+| Windows | MSVC | Visual Studio 2019+ |
+
+Set compiler explicitly to avoid version mismatches:
```bash
-cmake -S . -B build-xcode -G Xcode
-open build-xcode/osquery.xcodeproj
+export CC=clang-13
+export CXX=clang++-13
```
---
-## Development Tools
+## ccache (Build Cache)
-Install these tools before starting development:
+`ccache` significantly speeds up incremental and clean builds by caching compiled objects.
-### All Platforms
+Install and enable:
```bash
-# Python tools for code generation
-pip3 install jinja2 pexpect six
+# Linux
+sudo apt-get install ccache
+
+# macOS
+brew install ccache
+
+# Verify
+ccache --version
```
-### Linux
+Configure in your shell profile:
```bash
-sudo apt-get install -y \
- clang-format \
- clang-tidy \
- ccache \
- valgrind \
- gdb
+export CCACHE_DIR="$HOME/.ccache"
+export PATH="/usr/lib/ccache:$PATH"
```
-### macOS
+CMake integration:
```bash
-brew install \
- clang-format \
- ccache \
- llvm
+cmake .. \
+ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
+ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
```
-### Windows
+---
-- Install [LLVM](https://releases.llvm.org/) for `clang-format` and `clang-tidy`
-- Configure `PATH` to include the LLVM `bin` directory
+## clang-format (Code Formatting)
----
+The project uses `clang-format` for consistent C++ code style.
-## Setting Up ccache (Highly Recommended)
+Install:
-`ccache` dramatically speeds up incremental rebuilds:
+```bash
+# Linux
+sudo apt-get install clang-format-13
+
+# macOS
+brew install clang-format
+```
+
+Format a file:
```bash
-# Install ccache
-sudo apt-get install ccache # Linux
-brew install ccache # macOS
-
-# Enable in CMake
-cmake -S . -B build \
- -G Ninja \
- -DCMAKE_BUILD_TYPE=Debug \
- -DCMAKE_C_COMPILER_LAUNCHER=ccache \
- -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
+clang-format -i openframe/openframe_encryption_service.cpp
+```
+
+Check formatting without modifying:
+
+```bash
+clang-format --dry-run --Werror openframe/openframe_encryption_service.cpp
```
---
-## Generate compile_commands.json for clangd
+## Python Tools (Code Generation)
-For full IntelliSense support with `clangd`, generate the compilation database:
+osquery uses Python scripts for table code generation and CI tasks:
```bash
-cmake -S . -B build \
- -G Ninja \
- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-
-# Link to project root (required by clangd)
-ln -sf build/compile_commands.json compile_commands.json
+pip3 install jinja2 six
```
---
## Environment Variables for Development
-| Variable | Purpose | Example |
-|---|---|---|
-| `OSQUERY_EXTENSIONS_SOCKET` | Extension manager socket path | `/tmp/osquery.em` |
-| `OSQUERY_CONFIG_PATH` | Override default config location | `./test.conf` |
-| `OSQUERY_DB_PATH` | Custom database path for development | `/tmp/osquery-dev.db` |
-| `OPENSSL_ROOT_DIR` | OpenSSL installation path (Windows/macOS) | `/usr/local/opt/openssl` |
+| Variable | Purpose | Example Value |
+|----------|---------|--------------|
+| `CC` | C compiler path | `/usr/bin/clang-13` |
+| `CXX` | C++ compiler path | `/usr/bin/clang++-13` |
+| `CCACHE_DIR` | ccache storage directory | `$HOME/.ccache` |
+| `OPENFRAME_TOKEN_PATH` | Path to encrypted token file | `/etc/openframe/token.enc` |
+| `OPENFRAME_SECRET_KEY` | AES-256 secret key for token decryption | Refer to your environment configuration |
+
+---
+
+## Generating compile_commands.json
-Set in your shell profile or export before building:
+The `compile_commands.json` file is required by clangd for code intelligence:
```bash
-export OPENSSL_ROOT_DIR="/usr/local/opt/openssl@3"
+cd build
+cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
```
-On Windows:
+Then symlink to the project root so clangd and editors find it:
```bash
-set OPENSSL_ROOT_DIR=C:\OpenSSL-Win64
+ln -s build/compile_commands.json compile_commands.json
```
---
-## Code Formatting
-
-osquery enforces formatting with `clang-format`. The configuration is in `.clang-format` at the repository root.
+## Verifying Your Environment
```bash
-# Format a single file
-clang-format -i osquery/core/init.cpp
+# Confirm compiler works
+clang++ --std=c++17 -o /dev/null -x c++ /dev/null
-# Check formatting without modifying
-clang-format --dry-run --Werror osquery/core/init.cpp
+# Confirm CMake finds Clang
+cmake .. -DCMAKE_CXX_COMPILER=clang++ --trace-source=CMakeLists.txt 2>&1 | head -20
-# Format all C++ files in a directory
-find osquery/core -name "*.cpp" -o -name "*.h" | xargs clang-format -i
+# Confirm OpenSSL is available for the OpenFrame encryption service
+pkg-config --libs openssl
```
-
-The CI pipeline enforces formatting. Run format checks before submitting PRs.
-
----
-
-## Next Steps
-
-Once your environment is set up, proceed to the [Local Development Guide](local-development.md) for instructions on building, running, and debugging osquery locally.
diff --git a/docs/development/setup/local-development.md b/docs/development/setup/local-development.md
index da84e7144e8..d6572fc51dd 100644
--- a/docs/development/setup/local-development.md
+++ b/docs/development/setup/local-development.md
@@ -1,6 +1,6 @@
# Local Development Guide
-This guide walks you through cloning, building, running, and debugging osquery with OpenFrame on your local machine.
+This guide covers cloning the repository, building locally, running osquery in development mode, and configuring a debugger.
---
@@ -11,176 +11,185 @@ git clone https://github.com/flamingo-stack/osquery.git
cd osquery
```
+Initialize submodules if any are present:
+
+```bash
+git submodule update --init --recursive
+```
+
+---
+
+## Directory Structure
+
+```text
+.
+βββ osquery/ # Core osquery C++ source
+βββ openframe/ # OpenFrame authentication extensions
+βββ plugins/ # Config, logger, database, distributed plugins
+βββ libraries/ # Vendored third-party libraries
+βββ tools/ # Code generation scripts, CI tooling
+βββ external/ # Extension SDK examples
+βββ tests/ # Integration test suite
+βββ CMakeLists.txt # Root CMake configuration
+βββ package.json # Documentation pipeline tooling (not a build dep)
+```
+
---
-## Build Configurations
+## Build for Local Development
-### Debug Build (Recommended for Development)
+### 1. Create a Build Directory
+
+Always build out-of-source:
+
+```bash
+mkdir build
+cd build
+```
+
+### 2. Configure CMake (Debug Mode)
```bash
-cmake -S . -B build \
- -G Ninja \
+cmake .. \
+ -DCMAKE_C_COMPILER=clang \
+ -DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-
-cmake --build build --parallel $(nproc)
```
-> Debug builds include full debug symbols and disable optimizations, making debugging straightforward.
+> **Tip:** `CMAKE_EXPORT_COMPILE_COMMANDS=ON` generates `compile_commands.json` for IDE code intelligence.
-### RelWithDebInfo (Recommended for Testing)
+### 3. Build All Targets
```bash
-cmake -S . -B build \
- -G Ninja \
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
-
-cmake --build build --parallel $(nproc)
+cmake --build . --parallel $(nproc)
```
-### Release Build
+### 4. Build Specific Targets
-```bash
-cmake -S . -B build \
- -G Ninja \
- -DCMAKE_BUILD_TYPE=Release
+Build only the interactive shell:
-cmake --build build --parallel $(nproc)
+```bash
+cmake --build . --target osqueryi --parallel $(nproc)
```
-### Build with Tests Enabled
+Build only the daemon:
```bash
-cmake -S . -B build \
- -G Ninja \
- -DCMAKE_BUILD_TYPE=Debug \
- -DOSQUERY_BUILD_TESTS=ON
+cmake --build . --target osqueryd --parallel $(nproc)
+```
+
+Build the test suite:
-cmake --build build --parallel $(nproc)
+```bash
+cmake --build . --target osquery_tests --parallel $(nproc)
```
---
-## Running osquery Locally
+## Running Locally
-### Interactive Shell (`osqueryi`)
+### Interactive Shell (osqueryi)
```bash
-./build/osquery/osqueryi
+./osquery/osqueryi
```
-```sql
-osquery> SELECT hostname, cpu_brand FROM system_info;
-osquery> .tables
-osquery> .schema processes
-osquery> .quit
+With verbose output:
+
+```bash
+./osquery/osqueryi --verbose
```
-### Daemon (`osqueryd`)
+Disable logging for cleaner development output:
```bash
-# Create a minimal development config
-cat > /tmp/osquery-dev.conf <<'EOF'
+./osquery/osqueryi --disable_logging=true
+```
+
+### Daemon (osqueryd)
+
+Create a minimal development config:
+
+```bash
+cat > /tmp/dev_osquery.conf << 'EOF'
{
"options": {
+ "config_plugin": "filesystem",
"logger_plugin": "filesystem",
- "logger_path": "/tmp/osquery-dev-logs",
- "database_path": "/tmp/osquery-dev.db",
+ "logger_path": "/tmp/osquery_dev_logs",
+ "disable_logging": false,
"schedule_splay_percent": 0
},
"schedule": {
"system_info": {
- "query": "SELECT hostname, cpu_brand FROM system_info;",
- "interval": 60
+ "query": "SELECT hostname, cpu_type FROM system_info;",
+ "interval": 10
}
}
}
EOF
-
-mkdir -p /tmp/osquery-dev-logs
-
-./build/osquery/osqueryd \
- --config_path=/tmp/osquery-dev.conf \
- --verbose \
- --ephemeral
```
----
-
-## Development Flags
-
-These flags are useful during local development:
-
-| Flag | Purpose |
-|---|---|
-| `--verbose` | Enable verbose logging output |
-| `--ephemeral` | Use in-memory database (no disk writes) |
-| `--disable_watchdog` | Disable resource watchdog (easier debugging) |
-| `--disable_events` | Disable event publishers (faster startup) |
-| `--disable_logging` | Suppress all logger output |
-| `--allow_unsafe` | Allow loading unsigned extensions |
-| `--extensions_timeout=10` | Extension connection timeout in seconds |
-
-Example for a minimal debug session:
+Run the daemon in the foreground (useful during development):
```bash
-./build/osquery/osqueryi \
- --verbose \
- --disable_events \
- --ephemeral
+./osquery/osqueryd \
+ --config_path=/tmp/dev_osquery.conf \
+ --ephemeral=true \
+ --disable_database=true \
+ --verbose
```
+> **Note:** `--ephemeral=true --disable_database=true` uses the in-memory database, avoiding RocksDB file locking issues during rapid iteration.
+
---
## Incremental Builds
-After making source changes, only rebuild changed targets:
+After modifying a source file, CMake only recompiles the changed translation units:
```bash
-# Rebuild only the osqueryi binary
-cmake --build build --target osqueryi
+cd build
+cmake --build . --parallel $(nproc)
+```
-# Rebuild only the osqueryd binary
-cmake --build build --target osqueryd
+After adding a new source file, re-run CMake first:
-# Rebuild a specific test target
-cmake --build build --target osquery_core_tests
+```bash
+cmake ..
+cmake --build . --parallel $(nproc)
```
---
-## Debugging
+## Debug Configuration
-### Using GDB (Linux)
+### Using LLDB (macOS / Linux)
```bash
-# Build with debug symbols
-cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
-cmake --build build --parallel $(nproc)
+lldb ./osquery/osqueryi
+(lldb) run --verbose
+```
-# Launch with GDB
-gdb ./build/osquery/osqueryi
+Set a breakpoint:
-# In GDB:
-# (gdb) set args --verbose --ephemeral
-# (gdb) break osquery::Initializer::start
-# (gdb) run
+```bash
+(lldb) breakpoint set --name OpenframeEncryptionService::decrypt
+(lldb) run
```
-### Using LLDB (macOS)
+### Using GDB (Linux)
```bash
-lldb ./build/osquery/osqueryi
-
-# In LLDB:
-# (lldb) settings set -- target.run-args "--verbose" "--ephemeral"
-# (lldb) b osquery::Initializer::start
-# (lldb) run
+gdb ./osquery/osqueryi
+(gdb) break OpenframeTokenExtractor::extractToken
+(gdb) run --verbose
```
-### Using VS Code Debugger
+### VS Code Debug Configuration
-Add to `.vscode/launch.json`:
+Create `.vscode/launch.json`:
```json
{
@@ -188,23 +197,43 @@ Add to `.vscode/launch.json`:
"configurations": [
{
"name": "Debug osqueryi",
- "type": "cppdbg",
+ "type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/build/osquery/osqueryi",
- "args": ["--verbose", "--ephemeral", "--disable_events"],
- "stopAtEntry": false,
+ "args": ["--verbose", "--disable_database=true"],
"cwd": "${workspaceFolder}",
- "environment": [],
- "externalConsole": false,
- "MIMode": "gdb",
- "miDebuggerPath": "/usr/bin/gdb",
- "setupCommands": [
- {
- "description": "Enable pretty-printing",
- "text": "-enable-pretty-printing",
- "ignoreFailures": true
- }
- ]
+ "preLaunchTask": "cmake-build"
+ },
+ {
+ "name": "Debug osqueryd",
+ "type": "lldb",
+ "request": "launch",
+ "program": "${workspaceFolder}/build/osquery/osqueryd",
+ "args": [
+ "--config_path=/tmp/dev_osquery.conf",
+ "--verbose",
+ "--ephemeral=true"
+ ],
+ "cwd": "${workspaceFolder}"
+ }
+ ]
+}
+```
+
+Create `.vscode/tasks.json` for the pre-launch build task:
+
+```json
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "cmake-build",
+ "type": "shell",
+ "command": "cmake --build build --parallel $(nproc)",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
}
]
}
@@ -212,68 +241,91 @@ Add to `.vscode/launch.json`:
---
-## Developing the OpenFrame Layer
+## Running Unit Tests
+
+```bash
+cd build
-The OpenFrame components live in the `openframe/` directory:
+# Run all unit tests
+ctest --parallel $(nproc) --output-on-failure
-```text
-openframe/
-βββ openframe_authorization_manager.h/.cpp # JWT token lifecycle
-βββ openframe_authorization_manager_provider.h
-βββ openframe_encryption_service.h/.cpp # AES-256-GCM via OpenSSL
-βββ openframe_token_extractor.h/.cpp # Token acquisition
-βββ openframe_token_refresher.h/.cpp # Background token renewal
+# Run a specific test binary
+./osquery/osquery_tests --gtest_filter=ConfigTests.*
+
+# Run with verbose output
+./osquery/osquery_tests --gtest_filter=* --gtest_verbose=all
```
-When modifying OpenFrame components, rebuild only the affected target:
+---
+
+## Watching for Changes
+
+osquery doesn't have a built-in watch mode. Use `entr` or a similar tool to trigger rebuilds on file changes:
```bash
-cmake --build build --target openframe_auth
+# Linux/macOS - rebuild on any .cpp or .h change under osquery/ or openframe/
+find osquery/ openframe/ -name '*.cpp' -o -name '*.h' | \
+ entr -c cmake --build build --parallel $(nproc) --target osqueryi
```
-Test the encryption service independently by linking against it in a test binary.
+Install `entr` if needed:
----
+```bash
+# Ubuntu/Debian
+sudo apt-get install entr
-## Working with Virtual Tables
+# macOS
+brew install entr
+```
-To add a new virtual table:
+---
-1. Create schema and implementation in `osquery/tables//`
-2. Register the table in the appropriate CMake target
-3. Run the code generator to update schema definitions:
+## Cleaning the Build
+
+Remove build artifacts without reconfiguring:
```bash
-python3 tools/codegen/gentable.py osquery/tables/my_category/my_table.table
+cmake --build build --target clean
```
-4. Rebuild and test:
+Full clean (delete build directory):
```bash
-cmake --build build --target osqueryi
-./build/osquery/osqueryi
-osquery> .tables my_table
+rm -rf build/
```
---
-## Log Output Locations
+## Adding a New OpenFrame Source File
-| Mode | Default Log Path |
-|---|---|
-| Daemon (Linux) | `/var/log/osquery/` |
-| Daemon (macOS) | `/var/log/osquery/` |
-| Daemon (Windows) | `C:\ProgramData\osquery\log\` |
-| Development override | Set `--logger_path=/tmp/my-logs` |
+When adding a new C++ source file to the `openframe/` directory:
----
+1. Create the `.h` and `.cpp` files.
+2. Add the source to the relevant `CMakeLists.txt`:
-## Clean Rebuild
+```cmake
+target_sources(openframe_lib PRIVATE
+ openframe/openframe_new_component.cpp
+)
+```
-If you encounter stale build artifacts:
+3. Re-run CMake and rebuild:
```bash
-rm -rf build/
-cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
-cmake --build build --parallel $(nproc)
+cd build
+cmake ..
+cmake --build . --parallel $(nproc)
```
+
+---
+
+## Useful CMake Flags for Development
+
+| Flag | Description |
+|------|-------------|
+| `-DCMAKE_BUILD_TYPE=Debug` | Include debug symbols |
+| `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` | Generate `compile_commands.json` |
+| `-DOSQUERY_DISABLE_DATABASE=ON` | Skip RocksDB build (faster for table dev) |
+| `-DOSQUERY_NO_DEBUG_SYMBOLS=ON` | Reduce binary size |
+| `-DCMAKE_C_COMPILER_LAUNCHER=ccache` | Enable ccache for C compilation |
+| `-DCMAKE_CXX_COMPILER_LAUNCHER=ccache` | Enable ccache for C++ compilation |
diff --git a/docs/development/testing/README.md b/docs/development/testing/README.md
deleted file mode 100644
index 550d7e68a8e..00000000000
--- a/docs/development/testing/README.md
+++ /dev/null
@@ -1,310 +0,0 @@
-# Testing Guide
-
-osquery uses **Google Test** (GTest) and **Google Mock** (GMock) for unit and integration testing. Tests are organized alongside the source code in `tests/` subdirectories within each module.
-
----
-
-## Test Structure and Organization
-
-```text
-osquery/
-βββ core/
-β βββ tests/
-β β βββ flags_tests.cpp
-β β βββ query_tests.cpp
-β β βββ system_test.cpp
-β β βββ tables_tests.cpp
-βββ sql/
-β βββ tests/
-β βββ sql.cpp
-β βββ virtual_table.cpp
-βββ events/
-β βββ tests/
-β βββ events_tests.cpp
-β βββ linux/
-β βββ inotify_tests.cpp
-β βββ bpf/
-βββ config/
-β βββ tests/
-β βββ config_tests.cpp
-β βββ packs.cpp
-βββ database/
-β βββ tests/
-βββ distributed/
-β βββ tests/
-βββ extensions/
- βββ tests/
-
-tests/
-βββ integration/
- βββ tables/ # Integration tests for all virtual tables
- βββ processes.cpp
- βββ users.cpp
- βββ listening_ports.cpp
- βββ ...
-
-plugins/
-βββ */tests/ # Plugin-level tests
-```
-
-### Test Categories
-
-| Category | Location | Description |
-|---|---|---|
-| **Unit Tests** | `osquery/*/tests/` | Fast, isolated, no OS dependencies |
-| **Integration Tests** | `tests/integration/tables/` | Live table queries against the real OS |
-| **Benchmark Tests** | `osquery/*/benchmarks/` | Performance measurements |
-| **Extension Tests** | `osquery/extensions/tests/` | IPC and Thrift extension round-trips |
-| **Plugin Tests** | `plugins/*/tests/` | Logger, config, and database plugins |
-
----
-
-## Building Tests
-
-Tests must be explicitly enabled at CMake configure time:
-
-```bash
-cmake -S . -B build \
- -G Ninja \
- -DCMAKE_BUILD_TYPE=Debug \
- -DOSQUERY_BUILD_TESTS=ON
-
-cmake --build build --parallel $(nproc)
-```
-
----
-
-## Running Tests
-
-### Run All Tests
-
-```bash
-cd build
-ctest --output-on-failure
-```
-
-### Run Tests in Parallel
-
-```bash
-cd build
-ctest --output-on-failure --parallel $(nproc)
-```
-
-### Run a Specific Test Suite
-
-```bash
-cd build
-
-# Run core tests
-ctest -R "osquery_core_tests" --output-on-failure
-
-# Run SQL tests
-ctest -R "osquery_sql_tests" --output-on-failure
-
-# Run config tests
-ctest -R "osquery_config_tests" --output-on-failure
-
-# Run events tests
-ctest -R "osquery_events_tests" --output-on-failure
-
-# Run integration table tests
-ctest -R "integration" --output-on-failure
-```
-
-### Run Tests by Keyword
-
-```bash
-cd build
-ctest -R "tls" --output-on-failure
-ctest -R "database" --output-on-failure
-ctest -R "extension" --output-on-failure
-```
-
-### Verbose Test Output
-
-```bash
-cd build
-ctest -V -R "osquery_core_tests"
-```
-
----
-
-## Writing New Tests
-
-### Unit Test Template
-
-```cpp
-#include
-#include
-
-#include "osquery/my_module/my_class.h"
-
-namespace osquery {
-
-class MyClassTest : public ::testing::Test {
- protected:
- void SetUp() override {
- // Per-test setup
- }
-
- void TearDown() override {
- // Per-test cleanup
- }
-};
-
-TEST_F(MyClassTest, BasicOperation) {
- MyClass obj;
- EXPECT_EQ(obj.doSomething(), expected_value);
-}
-
-TEST_F(MyClassTest, HandlesEdgeCase) {
- MyClass obj;
- EXPECT_THROW(obj.doSomethingInvalid(), std::runtime_error);
-}
-
-} // namespace osquery
-```
-
-### Virtual Table Integration Test Template
-
-```cpp
-#include "tests/integration/tables/helper.h"
-
-namespace osquery {
-namespace table_tests {
-
-class MyTableTest : public testing::Test {};
-
-TEST_F(MyTableTest, test_sanity) {
- // Validate table schema and basic query
- auto const data = execute_query("SELECT * FROM my_table;");
- ASSERT_GT(data.size(), 0ul);
-
- // Validate specific column presence and types
- ValidateSchema(
- data,
- {
- {"column_one", BIGINT_TYPE, CHECK_GT, 0, CHECK_LT, INT_MAX},
- {"column_two", TEXT_TYPE, CHECK_NON_EMPTY},
- }
- );
-}
-
-} // namespace table_tests
-} // namespace osquery
-```
-
-### Using GMock for Dependencies
-
-```cpp
-#include
-#include "osquery/database/database.h"
-
-class MockDatabase : public IDatabaseInterface {
- public:
- MOCK_METHOD(Status, putBatch,
- (const std::string& domain,
- const DatabaseStringValueList& data),
- (override));
-
- MOCK_METHOD(Status, get,
- (const std::string& domain,
- const std::string& key,
- std::string& value),
- (const, override));
-};
-
-TEST(MyServiceTest, PersistsData) {
- MockDatabase db;
- EXPECT_CALL(db, putBatch(testing::_, testing::_))
- .Times(1)
- .WillOnce(testing::Return(Status::success()));
-
- MyService service(db);
- auto result = service.persist("key", "value");
- EXPECT_TRUE(result.ok());
-}
-```
-
----
-
-## Test Helpers
-
-The integration test suite includes shared helpers in `tests/integration/tables/helper.h`:
-
-| Helper | Purpose |
-|---|---|
-| `execute_query(sql)` | Execute SQL and return rows |
-| `ValidateSchema(data, validators)` | Assert column types and value ranges |
-| `CHECK_GT`, `CHECK_LT` | Numeric range validators |
-| `CHECK_NON_EMPTY` | String non-emptiness check |
-
----
-
-## Benchmark Tests
-
-Benchmarks measure performance of hot paths:
-
-```bash
-# Build benchmarks
-cmake -S . -B build -G Ninja \
- -DCMAKE_BUILD_TYPE=Release \
- -DOSQUERY_BUILD_BENCHMARKS=ON
-cmake --build build --parallel $(nproc)
-
-# Run SQL benchmarks
-./build/osquery/sql/benchmarks/sql_benchmarks
-
-# Run events benchmarks
-./build/osquery/events/benchmarks/events_benchmarks
-```
-
----
-
-## Coverage Requirements
-
-While no mandatory coverage threshold is enforced in CI currently, the project encourages:
-
-- **Unit tests** for all new core module functionality
-- **Integration tests** for every new virtual table
-- **Error path coverage** for all error handling branches
-- **Mock-based tests** for components with external dependencies (network, database)
-
-When contributing new virtual tables, a corresponding integration test in `tests/integration/tables/` is expected.
-
----
-
-## Platform-Specific Tests
-
-Some tests only run on specific platforms:
-
-```cpp
-// Linux-only test
-#ifdef __linux__
-TEST_F(AuditTest, LinuxAuditPublisher) {
- // Linux-specific audit test
-}
-#endif
-
-// macOS-only test
-#ifdef __APPLE__
-TEST_F(FSEventsTest, FseventsPublisher) {
- // macOS FSEvents test
-}
-#endif
-```
-
-The CMake build system automatically includes platform-appropriate test targets.
-
----
-
-## Continuous Integration
-
-Tests run automatically in CI on every pull request. The CI pipeline:
-
-1. Builds with `-DOSQUERY_BUILD_TESTS=ON`
-2. Runs `ctest --output-on-failure`
-3. Enforces `clang-format` compliance
-4. Checks copyright headers (via `tools/ci/scripts/check_copyright_headers.py`)
-
-All tests must pass before a PR can be merged.
diff --git a/docs/diagrams/architecture/README-10.mmd b/docs/diagrams/architecture/README-10.mmd
deleted file mode 100644
index 9de352b6a66..00000000000
--- a/docs/diagrams/architecture/README-10.mmd
+++ /dev/null
@@ -1,4 +0,0 @@
-flowchart TD
- Caller["Module"] --> Client["HTTP Client"]
- Client --> TLS["TLS Handshake"]
- TLS --> Remote["Remote Server"]
diff --git a/docs/diagrams/architecture/README-11.mmd b/docs/diagrams/architecture/README-11.mmd
deleted file mode 100644
index dbc77c3eaf7..00000000000
--- a/docs/diagrams/architecture/README-11.mmd
+++ /dev/null
@@ -1,4 +0,0 @@
-flowchart TD
- Caller["Subsystem"] --> FS["Filesystem API"]
- FS --> POSIX["POSIX Implementation"]
- FS --> Windows["Windows Implementation"]
diff --git a/docs/diagrams/architecture/README-2.mmd b/docs/diagrams/architecture/README-2.mmd
index 15cf680aafe..01f65151dd1 100644
--- a/docs/diagrams/architecture/README-2.mmd
+++ b/docs/diagrams/architecture/README-2.mmd
@@ -1,11 +1,14 @@
flowchart TD
- Start["Process Start"] --> Init["Initializer"]
- Init --> Flags["Parse Flags"]
- Init --> Registry["Initialize Registry"]
- Init --> DBInit["Initialize Database"]
- Init --> ExtMgr["Start Extension Manager"]
- Init --> ConfigLoad["Load Configuration"]
- ConfigLoad --> Schedule["Build Schedule"]
- Schedule --> QueryExec["Execute Queries"]
- QueryExec --> Log["Log Results"]
- Log --> End["Runtime Loop"]
+ Source["Scheduled Or Distributed Query"] --> Scheduler["Configuration And Packs"]
+ Scheduler --> SQLPlugin["SQLiteSQLPlugin"]
+ SQLPlugin --> SQLiteCore["SQLite Engine"]
+ SQLiteCore --> VTables["Virtual Tables"]
+ VTables --> TablePlugins["Table Plugins"]
+
+ SQLiteCore --> QueryState["Query State And Diff"]
+ QueryState --> DB["Database Backend"]
+ QueryState --> Diff["DiffResults"]
+
+ Diff --> LogItem["QueryLogItem"]
+ LogItem --> Logger["Logger Plugin"]
+ Logger --> External["External Logging System"]
diff --git a/docs/diagrams/architecture/README-3.mmd b/docs/diagrams/architecture/README-3.mmd
index 2bec5262176..e9aaea002ea 100644
--- a/docs/diagrams/architecture/README-3.mmd
+++ b/docs/diagrams/architecture/README-3.mmd
@@ -1,7 +1,6 @@
flowchart TD
- Query["SQL Query"] --> SQLite["SQLite Engine"]
- SQLite --> Module["sqlite3_module"]
- Module --> VirtualTable["VirtualTable Wrapper"]
- VirtualTable --> TablePlugin["TablePlugin"]
- TablePlugin --> OS["Operating System Data"]
- OS --> Rows["Rows Returned"]
+ Publisher["Event Publisher Plugin"] --> Subscriber["EventSubscriberPlugin"]
+ Subscriber --> DB["Database Backend"]
+ Subscriber --> SQLTable["Event Virtual Table"]
+ SQLTable --> Query["SELECT From Event Table"]
+ Query --> Logging["Logging And Query Metadata"]
diff --git a/docs/diagrams/architecture/README-4.mmd b/docs/diagrams/architecture/README-4.mmd
index 7cb68c8186b..fbfca6eb432 100644
--- a/docs/diagrams/architecture/README-4.mmd
+++ b/docs/diagrams/architecture/README-4.mmd
@@ -1,6 +1,7 @@
flowchart TD
- Source["Config Source (File / TLS / Extension)"] --> ConfigCore["Config Singleton"]
- ConfigCore --> Parsers["ConfigParserPlugins"]
- Parsers --> Schedule["Scheduled Queries"]
- Schedule --> Scheduler["Query Scheduler"]
- Scheduler --> SQL["SQL Engine"]
+ Server["Remote Server"] --> TLSPlugin["Distributed TLS Plugin"]
+ TLSPlugin --> DistributedEngine["Distributed Querying"]
+ DistributedEngine --> SQL["SQL Engine"]
+ SQL --> Results["DistributedQueryResult"]
+ Results --> TLSPlugin
+ TLSPlugin --> Server
diff --git a/docs/diagrams/architecture/README-5.mmd b/docs/diagrams/architecture/README-5.mmd
deleted file mode 100644
index 15b3d86b3cc..00000000000
--- a/docs/diagrams/architecture/README-5.mmd
+++ /dev/null
@@ -1,6 +0,0 @@
-flowchart TD
- Publisher["EventPublisher"] --> EventFactory["EventFactory"]
- Subscriber["EventSubscriber"] --> EventFactory
- EventFactory --> Callback["EventCallback"]
- Callback --> Storage["Database Storage"]
- SQL["SELECT *_events"] --> Subscriber
diff --git a/docs/diagrams/architecture/README-6.mmd b/docs/diagrams/architecture/README-6.mmd
deleted file mode 100644
index f6966640dec..00000000000
--- a/docs/diagrams/architecture/README-6.mmd
+++ /dev/null
@@ -1,6 +0,0 @@
-flowchart TD
- Exec["Query Execution"] --> Diff["DiffResults"]
- Diff --> LogItem["QueryLogItem"]
- LogItem --> Serialize["JSON Serialization"]
- Serialize --> Logger["LoggerPlugin"]
- Logger --> Sink["External Backend"]
diff --git a/docs/diagrams/architecture/README-7.mmd b/docs/diagrams/architecture/README-7.mmd
deleted file mode 100644
index b995aa1bd07..00000000000
--- a/docs/diagrams/architecture/README-7.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- Modules["Core Modules"] --> Interface["IDatabaseInterface"]
- Interface --> Plugin["Database Plugin"]
- Plugin --> RocksDB["Persistent Backend"]
- Plugin --> Ephemeral["In-Memory Backend"]
diff --git a/docs/diagrams/architecture/README-8.mmd b/docs/diagrams/architecture/README-8.mmd
deleted file mode 100644
index f90914fba8e..00000000000
--- a/docs/diagrams/architecture/README-8.mmd
+++ /dev/null
@@ -1,7 +0,0 @@
-flowchart TD
- Server["Central Server"] --> TLS["TLS Distributed Plugin"]
- TLS --> Core["Distributed Core"]
- Core --> SQL["SQL Engine"]
- SQL --> Results["Results"]
- Results --> TLS
- TLS --> Server
diff --git a/docs/diagrams/architecture/README-9.mmd b/docs/diagrams/architecture/README-9.mmd
deleted file mode 100644
index 05f3210aec0..00000000000
--- a/docs/diagrams/architecture/README-9.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart LR
- Core["osquery Core"] --> Manager["Extension Manager"]
- Extension["External Extension"] --> Manager
- Manager --> Registry["RegistryFactory"]
- Core --> Extension
diff --git a/docs/diagrams/architecture/README.mmd b/docs/diagrams/architecture/README.mmd
index abd03ad683d..9d4393b5aa6 100644
--- a/docs/diagrams/architecture/README.mmd
+++ b/docs/diagrams/architecture/README.mmd
@@ -1,22 +1,26 @@
flowchart TD
- CLI["osqueryi / osqueryd"] --> Core["Core Init And Runtime"]
-
- Core --> Config["Configuration And Packs"]
+ Core["Core Runtime And Lifecycle"] --> Config["Configuration And Packs"]
Core --> SQL["SQL Engine And Virtual Tables"]
- Core --> Events["Eventing Framework"]
- Core --> Logging["Logging And Observability"]
- Core --> DB["Database And Storage Plugins"]
+ Core --> DB["Database Backend"]
+ Core --> Logging["Logging And Query Metadata"]
+ Core --> Events["Events Core And Subscriptions"]
+ Core --> Extensions["Extensions Framework"]
Core --> Distributed["Distributed Querying"]
- Core --> Extensions["Extensions And IPC"]
- Core --> HTTP["Remote HTTP Client"]
- Core --> FS["Filesystem And Path Utilities"]
Config --> SQL
Config --> Events
+ Config --> Logging
+
SQL --> Logging
+ SQL --> DB
+
Events --> DB
+ Events --> Logging
+
Distributed --> SQL
- Distributed --> HTTP
- Logging --> DB
+ Distributed --> DB
+ Distributed --> Logging
+
Extensions --> SQL
- Extensions --> DB
+ Extensions --> Config
+ Extensions --> Distributed
diff --git a/docs/diagrams/architecture/config-plugins-2.mmd b/docs/diagrams/architecture/config-plugins-2.mmd
new file mode 100644
index 00000000000..87c41852990
--- /dev/null
+++ b/docs/diagrams/architecture/config-plugins-2.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ Start["Start genConfig()"] --> CheckFile["Check config_path exists"]
+ CheckFile -->|"valid"| LoadDir["Resolve config_path.d/*.conf"]
+ LoadDir --> SortFiles["Sort files"]
+ SortFiles --> Merge["Append main config"]
+ Merge --> Output["Return map of source to JSON"]
+ CheckFile -->|"invalid"| Fail["Return failure Status"]
diff --git a/docs/diagrams/architecture/config-plugins-3.mmd b/docs/diagrams/architecture/config-plugins-3.mmd
new file mode 100644
index 00000000000..3f2e1e62041
--- /dev/null
+++ b/docs/diagrams/architecture/config-plugins-3.mmd
@@ -0,0 +1,14 @@
+flowchart TD
+ ConfigLoad["Config Updated"] --> ParseDecorators["Parse decorators JSON"]
+ ParseDecorators --> StoreQueries["Store queries by point"]
+ StoreQueries --> RunLoad["Run load decorators"]
+
+ Scheduler["Query Scheduler"] --> RunAlways["Run always decorators"]
+ Scheduler --> RunInterval["Run interval decorators"]
+
+ RunLoad --> SQLExec["Execute SQL"]
+ RunAlways --> SQLExec
+ RunInterval --> SQLExec
+
+ SQLExec --> DecorationStore["Store first row columns"]
+ DecorationStore --> Logger["Attach to logs"]
diff --git a/docs/diagrams/architecture/config-plugins-4.mmd b/docs/diagrams/architecture/config-plugins-4.mmd
new file mode 100644
index 00000000000..58d3717a3bc
--- /dev/null
+++ b/docs/diagrams/architecture/config-plugins-4.mmd
@@ -0,0 +1,13 @@
+flowchart TD
+ ConfigUpdate["Config Update"] --> RemoveOld["Remove existing files for source"]
+ RemoveOld --> ParseFilePaths["Parse file_paths"]
+ RemoveOld --> ParseQuery["Parse file_paths_query"]
+ RemoveOld --> ParseAccess["Parse file_accesses"]
+ RemoveOld --> ParseExclude["Parse exclude_paths"]
+
+ ParseFilePaths --> Register["Config::addFile()"]
+ ParseQuery --> SQLExec["Execute SQL query"]
+ SQLExec --> Register
+
+ ParseAccess --> AccessMap["Build access map"]
+ ParseExclude --> MergeExclude["Merge exclude paths"]
diff --git a/docs/diagrams/architecture/config-plugins-5.mmd b/docs/diagrams/architecture/config-plugins-5.mmd
new file mode 100644
index 00000000000..2a68339bac7
--- /dev/null
+++ b/docs/diagrams/architecture/config-plugins-5.mmd
@@ -0,0 +1,6 @@
+flowchart TD
+ ParseOptions["Parse options JSON"] --> Validate["Validate flag name"]
+ Validate -->|"invalid"| Warn["Log warning"]
+ Validate -->|"valid"| UpdateFlag["Flag::updateValue()"]
+ UpdateFlag --> CheckVerbose["Is verbosity option?"]
+ CheckVerbose -->|"yes"| Reconfigure["setVerboseLevel()"]
diff --git a/docs/diagrams/architecture/config-plugins-6.mmd b/docs/diagrams/architecture/config-plugins-6.mmd
new file mode 100644
index 00000000000..a02f3e3e54c
--- /dev/null
+++ b/docs/diagrams/architecture/config-plugins-6.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ ParseViews["Parse views JSON"] --> LoadExisting["Scan database keys"]
+ LoadExisting --> Compare["Compare old vs new"]
+ Compare -->|"changed or new"| DropOld["DROP VIEW"]
+ DropOld --> CreateNew["CREATE VIEW AS query"]
+ CreateNew --> Persist["Store in database"]
+ Compare -->|"removed"| Remove["Delete database entry"]
diff --git a/docs/diagrams/architecture/config-plugins-7.mmd b/docs/diagrams/architecture/config-plugins-7.mmd
new file mode 100644
index 00000000000..bfd2c01c15e
--- /dev/null
+++ b/docs/diagrams/architecture/config-plugins-7.mmd
@@ -0,0 +1,10 @@
+flowchart TD
+ Source["Filesystem or Remote Source"] --> ConfigPlugin["ConfigPlugin"]
+ ConfigPlugin --> ConfigCore["Config Core"]
+ ConfigCore --> ParserPlugins["ConfigParserPlugins"]
+ ParserPlugins --> RuntimeState["Runtime State"]
+
+ RuntimeState --> Scheduler["Query Scheduler"]
+ RuntimeState --> Logger
+ RuntimeState --> Events
+ RuntimeState --> SQL
diff --git a/docs/diagrams/architecture/config-plugins.mmd b/docs/diagrams/architecture/config-plugins.mmd
new file mode 100644
index 00000000000..43a0e8b56eb
--- /dev/null
+++ b/docs/diagrams/architecture/config-plugins.mmd
@@ -0,0 +1,18 @@
+flowchart TD
+ CLI["CLI Flags"] --> FilesystemPlugin["FilesystemConfigPlugin"]
+ FilesystemPlugin --> ConfigCore["Config Core"]
+ UpdatePlugin["UpdateConfigPlugin"] --> ConfigCore
+
+ ConfigCore --> DecoratorsParser["DecoratorsConfigParserPlugin"]
+ ConfigCore --> EventsParser["EventsConfigParserPlugin"]
+ ConfigCore --> FilePathsParser["FilePathsConfigParserPlugin"]
+ ConfigCore --> OptionsParser["OptionsConfigParserPlugin"]
+ ConfigCore --> ViewsParser["ViewsConfigParserPlugin"]
+
+ DecoratorsParser --> SQL["SQL Engine"]
+ FilePathsParser --> SQL
+ ViewsParser --> SQL
+
+ ViewsParser --> DB["Database Backend"]
+ DecoratorsParser --> Logger["Logger"]
+ EventsParser --> EventsCore["Events Framework"]
diff --git a/docs/diagrams/architecture/configuration-and-packs-2.mmd b/docs/diagrams/architecture/configuration-and-packs-2.mmd
index 058d1366de2..35594d81ffa 100644
--- a/docs/diagrams/architecture/configuration-and-packs-2.mmd
+++ b/docs/diagrams/architecture/configuration-and-packs-2.mmd
@@ -1,6 +1,6 @@
flowchart TD
- Start["ConfigRefreshRunner Start"] --> Wait["Sleep refresh_sec"]
- Wait --> Check["Interrupted?"]
- Check -->|No| Refresh["Config.refresh()"]
- Refresh --> Wait
- Check -->|Yes| End["End"]
+ Start["Thread Start"] --> Pause["Sleep refresh_sec"]
+ Pause --> Check["Interrupted?"]
+ Check -->|"Yes"| End["Stop"]
+ Check -->|"No"| Refresh["Config.refresh()"]
+ Refresh --> Pause
diff --git a/docs/diagrams/architecture/configuration-and-packs-3.mmd b/docs/diagrams/architecture/configuration-and-packs-3.mmd
index 14e23b18fcf..16fb7c1cd66 100644
--- a/docs/diagrams/architecture/configuration-and-packs-3.mmd
+++ b/docs/diagrams/architecture/configuration-and-packs-3.mmd
@@ -1,7 +1,9 @@
flowchart TD
- ConfigUpdate["Config Update"] --> BuildPacks["Create Pack Objects"]
- BuildPacks --> DiscoveryCheck["Discovery Queries"]
- DiscoveryCheck --> ActivePack["Active Pack"]
- ActivePack --> Scheduler["ScheduledQuery Execution"]
- Scheduler --> Performance["Query Performance Recording"]
- Scheduler --> Denylist["Denylist On Failure"]
+ Gen["Registry.call genConfig"] --> Update["Config.update()"]
+ Update --> Purge["Purge stale queries"]
+ Purge --> UpdateSource["updateSource(source)"]
+ UpdateSource --> Validate["Validate JSON"]
+ Validate --> Extract["Extract schedule and packs"]
+ Extract --> ApplyParsers["Apply config parsers"]
+ ApplyParsers --> Reconfigure["Reconfigure registries"]
+ Reconfigure --> Done["Config Valid"]
diff --git a/docs/diagrams/architecture/configuration-and-packs-4.mmd b/docs/diagrams/architecture/configuration-and-packs-4.mmd
index 31827beb892..3c90561d8cf 100644
--- a/docs/diagrams/architecture/configuration-and-packs-4.mmd
+++ b/docs/diagrams/architecture/configuration-and-packs-4.mmd
@@ -1,8 +1,5 @@
flowchart TD
- ConfigLoad["Config Load"] --> RunLoad["Run Load Decorators"]
- QueryExec["Query Execution"] --> RunAlways["Run Always Decorators"]
- IntervalTick["Interval Timer"] --> RunInterval["Run Interval Decorators"]
- RunLoad --> Decorations[("Decoration Store")]
- RunAlways --> Decorations
- RunInterval --> Decorations
- Decorations --> Logger["Status And Query Logs"]
+ Platform["Check Platform"] --> Version["Check Version"]
+ Version --> Shard["Check Shard"]
+ Shard --> Discovery["Run Discovery Queries"]
+ Discovery --> Active["Pack Active"]
diff --git a/docs/diagrams/architecture/configuration-and-packs-5.mmd b/docs/diagrams/architecture/configuration-and-packs-5.mmd
index 91bbcadc931..9d94b00e37c 100644
--- a/docs/diagrams/architecture/configuration-and-packs-5.mmd
+++ b/docs/diagrams/architecture/configuration-and-packs-5.mmd
@@ -1,11 +1,6 @@
flowchart TD
- Source["Config Source"] --> GenConfig["genConfig()"]
- GenConfig --> Update["Config.update()"]
- Update --> Purge["Purge Stale State"]
- Purge --> UpdateSource["updateSource()"]
- UpdateSource --> ParseJSON["Validate And Parse JSON"]
- ParseJSON --> BuildSchedule["Create Packs And Schedule"]
- BuildSchedule --> ApplyParsers["Apply ConfigParserPlugins"]
- ApplyParsers --> Reconfigure["Registry.configure()"]
- Reconfigure --> EventNotify["EventFactory.configUpdate()"]
- EventNotify --> Ready["Runtime Updated"]
+ Failure["Query Failure"] --> Persist["Persist to Database"]
+ Persist --> Denylist["Add to Denylist"]
+ Denylist --> Skip["Skip During Scheduling"]
+ Skip --> Expire["Expiration Check"]
+ Expire -->|"Expired"| Reactivate["Allow Execution"]
diff --git a/docs/diagrams/architecture/configuration-and-packs-6.mmd b/docs/diagrams/architecture/configuration-and-packs-6.mmd
new file mode 100644
index 00000000000..36700dbe79c
--- /dev/null
+++ b/docs/diagrams/architecture/configuration-and-packs-6.mmd
@@ -0,0 +1,4 @@
+flowchart TD
+ Update["Successful Update"] --> Backup["Backup Config Sources"]
+ Failure["Refresh Failure"] --> Restore["Restore From Database"]
+ Restore --> Update
diff --git a/docs/diagrams/architecture/configuration-and-packs-7.mmd b/docs/diagrams/architecture/configuration-and-packs-7.mmd
new file mode 100644
index 00000000000..4a142d2e3a1
--- /dev/null
+++ b/docs/diagrams/architecture/configuration-and-packs-7.mmd
@@ -0,0 +1,4 @@
+flowchart LR
+ SourceA["Source A Hash"] --> Combine["Combine Hashes"]
+ SourceB["Source B Hash"] --> Combine
+ Combine --> Global["Global Config Hash"]
diff --git a/docs/diagrams/architecture/configuration-and-packs.mmd b/docs/diagrams/architecture/configuration-and-packs.mmd
index 3a720d6d6c3..66ce753920e 100644
--- a/docs/diagrams/architecture/configuration-and-packs.mmd
+++ b/docs/diagrams/architecture/configuration-and-packs.mmd
@@ -1,15 +1,10 @@
flowchart TD
- ConfigPlugin["Config Plugin Registry"] --> ConfigCore["Config Singleton"]
- ConfigCore --> RefreshRunner["ConfigRefreshRunner"]
- ConfigCore --> Schedule["Schedule"]
- Schedule --> Pack["Pack"]
- ConfigCore --> Parsers["ConfigParserPlugins"]
- Parsers --> OptionsParser["Options Parser"]
- Parsers --> FilePathsParser["File Paths Parser"]
- Parsers --> DecoratorsParser["Decorators Parser"]
- Parsers --> EventsParser["Events Parser"]
- Parsers --> ViewsParser["Views Parser"]
- ConfigCore --> Database[("Persistent Database")]
- Schedule --> Logging["Logging And Query Observability"]
- Schedule --> SQLEngine["SQL Engine And Virtual Tables"]
- Parsers --> EventFramework["Eventing Framework"]
+ ConfigPlugin["Config Plugin Registry"] -->|"genConfig"| ConfigCore["Config Singleton"]
+ ConfigCore -->|"updateSource"| JSONValidation["JSON Validation"]
+ JSONValidation --> Packs["Pack Objects"]
+ Packs --> Schedule["Schedule Manager"]
+ Schedule --> SQL["SQL Engine"]
+ Schedule --> Logger["Logger Plugins"]
+ ConfigCore --> Database["Database Backend"]
+ ConfigCore --> EventFactory["Event Factory"]
+ ConfigCore --> Registry["Plugin Registry"]
diff --git a/docs/diagrams/architecture/core-init-and-runtime-2.mmd b/docs/diagrams/architecture/core-init-and-runtime-2.mmd
deleted file mode 100644
index 12303b48e3e..00000000000
--- a/docs/diagrams/architecture/core-init-and-runtime-2.mmd
+++ /dev/null
@@ -1,15 +0,0 @@
-sequenceDiagram
- participant Main
- participant Initializer
- participant Registry
- participant Config
- participant Extensions
- participant Events
-
- Main->>Initializer: Construct(argc, argv)
- Initializer->>Initializer: Parse flags
- Initializer->>Registry: registryAndPluginInit()
- Initializer->>Extensions: startExtensionManager()
- Initializer->>Config: load()
- Initializer->>Events: attachEvents()
- Initializer->>Initializer: start()
diff --git a/docs/diagrams/architecture/core-init-and-runtime-3.mmd b/docs/diagrams/architecture/core-init-and-runtime-3.mmd
deleted file mode 100644
index 6f1c2a8d3fd..00000000000
--- a/docs/diagrams/architecture/core-init-and-runtime-3.mmd
+++ /dev/null
@@ -1,8 +0,0 @@
-flowchart LR
- Macro["FLAG / CLI_FLAG Macros"] --> FlagCreate["Flag::create()"]
- FlagCreate --> FlagRegistry["Internal Flag Map"]
-
- CLI["Command Line"] --> Parse["ParseCommandLineFlags"]
- Config["Config Options"] --> Update["Flag::updateValue()"]
-
- FlagRegistry --> Runtime["Runtime Access"]
diff --git a/docs/diagrams/architecture/core-init-and-runtime-4.mmd b/docs/diagrams/architecture/core-init-and-runtime-4.mmd
deleted file mode 100644
index 3464c298d66..00000000000
--- a/docs/diagrams/architecture/core-init-and-runtime-4.mmd
+++ /dev/null
@@ -1,7 +0,0 @@
-flowchart TD
- Watcher["Watcher Process"] --> Spawn["Spawn Worker"]
- Spawn --> Monitor["Monitor CPU And Memory"]
- Monitor --> Check{{"Limit Exceeded?"}}
- Check -->|"No"| Continue["Continue Monitoring"]
- Check -->|"Yes"| Kill["Stop Worker"]
- Kill --> Respawn["Respawn Worker"]
diff --git a/docs/diagrams/architecture/core-init-and-runtime-5.mmd b/docs/diagrams/architecture/core-init-and-runtime-5.mmd
deleted file mode 100644
index 50b08395e59..00000000000
--- a/docs/diagrams/architecture/core-init-and-runtime-5.mmd
+++ /dev/null
@@ -1,9 +0,0 @@
-flowchart TD
- AnyThread["Any Thread"] --> Request["requestShutdown()"]
- Request --> Signal["Condition Variable"]
- Signal --> MainThread["Main Thread"]
- MainThread --> StopServices["Dispatcher::stopServices()"]
- StopServices --> Join["Join Services"]
- Join --> StopEvents["EventFactory::end()"]
- StopEvents --> CloseDB["shutdownDatabase()"]
- CloseDB --> Exit["Return Exit Code"]
diff --git a/docs/diagrams/architecture/core-init-and-runtime-6.mmd b/docs/diagrams/architecture/core-init-and-runtime-6.mmd
deleted file mode 100644
index 83e50573800..00000000000
--- a/docs/diagrams/architecture/core-init-and-runtime-6.mmd
+++ /dev/null
@@ -1,7 +0,0 @@
-flowchart LR
- Flag["host_identifier Flag"] --> Mode{{"Mode"}}
- Mode -->|"uuid"| Hardware["Hardware UUID"]
- Mode -->|"instance"| Instance["Instance UUID"]
- Mode -->|"ephemeral"| Ephemeral["Random UUID"]
- Mode -->|"specified"| Specified["Configured Identifier"]
- Mode -->|"default"| Hostname["System Hostname"]
diff --git a/docs/diagrams/architecture/core-init-and-runtime-7.mmd b/docs/diagrams/architecture/core-init-and-runtime-7.mmd
deleted file mode 100644
index 0533bd82ae3..00000000000
--- a/docs/diagrams/architecture/core-init-and-runtime-7.mmd
+++ /dev/null
@@ -1,6 +0,0 @@
-flowchart TD
- SQL["SQL Query"] --> SQLite["SQLite Virtual Table API"]
- SQLite --> QueryContext["QueryContext"]
- QueryContext --> ConstraintMap["ConstraintMap"]
- ConstraintMap --> ConstraintList["ConstraintList"]
- ConstraintList --> TablePlugin["TablePlugin::generate()"]
diff --git a/docs/diagrams/architecture/core-init-and-runtime-8.mmd b/docs/diagrams/architecture/core-init-and-runtime-8.mmd
deleted file mode 100644
index dd5a802fe24..00000000000
--- a/docs/diagrams/architecture/core-init-and-runtime-8.mmd
+++ /dev/null
@@ -1,9 +0,0 @@
-flowchart TD
- Core["Core Init And Runtime"]
-
- Core --> Config["Configuration And Packs"]
- Core --> Logging["Logging And Query Observability"]
- Core --> Database["Database And Storage Plugins"]
- Core --> SQL["SQL Engine And Virtual Tables"]
- Core --> Events["Eventing Framework And Subscriptions"]
- Core --> Extensions["Extensions And IPC"]
diff --git a/docs/diagrams/architecture/core-init-and-runtime.mmd b/docs/diagrams/architecture/core-init-and-runtime.mmd
deleted file mode 100644
index 75bf4fac1e6..00000000000
--- a/docs/diagrams/architecture/core-init-and-runtime.mmd
+++ /dev/null
@@ -1,16 +0,0 @@
-flowchart TD
- Main["Main Entry Point"] --> Initializer["Initializer"]
-
- Initializer --> Flags["Flag System"]
- Initializer --> Registry["Registry And Plugins"]
- Initializer --> Database["Database Initialization"]
- Initializer --> ExtensionManager["Extension Manager"]
- Initializer --> Events["Event Factory"]
- Initializer --> Watchdog["Watcher / Worker Model"]
-
- Watchdog --> Worker["Worker Process"]
- Watchdog --> Extensions["Extension Processes"]
-
- Worker --> Tables["Virtual Tables"]
- Worker --> Scheduler["Query Scheduler"]
- Worker --> Logger["Logger Plugins"]
diff --git a/docs/diagrams/architecture/core-runtime-and-lifecycle-2.mmd b/docs/diagrams/architecture/core-runtime-and-lifecycle-2.mmd
new file mode 100644
index 00000000000..c0245a19ed1
--- /dev/null
+++ b/docs/diagrams/architecture/core-runtime-and-lifecycle-2.mmd
@@ -0,0 +1,5 @@
+flowchart LR
+ Define["FLAG Macro"] --> Create["Flag::create()"]
+ Create --> Registry["Flag Internal Map"]
+ Registry --> Query["getValue() / getType()"]
+ Registry --> Print["printFlags()"]
diff --git a/docs/diagrams/architecture/core-runtime-and-lifecycle-3.mmd b/docs/diagrams/architecture/core-runtime-and-lifecycle-3.mmd
new file mode 100644
index 00000000000..19fc4631fc7
--- /dev/null
+++ b/docs/diagrams/architecture/core-runtime-and-lifecycle-3.mmd
@@ -0,0 +1,11 @@
+flowchart TD
+ Initializer["Initializer"] --> Mode{{"ToolType"}}
+ Mode --> Shell["Shell Mode"]
+ Mode --> Daemon["Daemon Mode"]
+ Mode --> Extension["Extension Mode"]
+
+ Daemon --> Watchdog{{"Watchdog Enabled?"}}
+ Watchdog -->|"Yes"| Watcher["Watcher Process"]
+ Watchdog -->|"No"| DirectRun["Single Process Runtime"]
+
+ Watcher --> Worker["Worker Process"]
diff --git a/docs/diagrams/architecture/core-runtime-and-lifecycle-4.mmd b/docs/diagrams/architecture/core-runtime-and-lifecycle-4.mmd
new file mode 100644
index 00000000000..74c005f4a0c
--- /dev/null
+++ b/docs/diagrams/architecture/core-runtime-and-lifecycle-4.mmd
@@ -0,0 +1,6 @@
+flowchart TD
+ Signal["SIGTERM / SIGINT / SIGUSR1"] --> Handler["signalHandler()"]
+ Handler --> Request["requestShutdown()"]
+ Request --> Notify["Condition Variable Notify"]
+ Notify --> MainWait["waitForShutdown()"]
+ MainWait --> GracefulStop["Dispatcher::stopServices()"]
diff --git a/docs/diagrams/architecture/core-runtime-and-lifecycle-5.mmd b/docs/diagrams/architecture/core-runtime-and-lifecycle-5.mmd
new file mode 100644
index 00000000000..adbe3c7a76d
--- /dev/null
+++ b/docs/diagrams/architecture/core-runtime-and-lifecycle-5.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ ShutdownStart["Initializer::shutdown()"] --> StartAlarm["Spawn AlarmRunnable"]
+ StartAlarm --> StopServices["Stop & Join Services"]
+ StopServices --> EndEvents["EventFactory::end()"]
+ EndEvents --> ShutdownDB["shutdownDatabase()"]
+ ShutdownDB --> CancelAlarm["Interrupt AlarmRunnable"]
+ CancelAlarm --> Exit["Return Exit Code"]
diff --git a/docs/diagrams/architecture/core-runtime-and-lifecycle.mmd b/docs/diagrams/architecture/core-runtime-and-lifecycle.mmd
new file mode 100644
index 00000000000..6a3cef53adf
--- /dev/null
+++ b/docs/diagrams/architecture/core-runtime-and-lifecycle.mmd
@@ -0,0 +1,24 @@
+flowchart TD
+ Entry["Process Entry Point"] --> Init["Initializer Constructor"]
+ Init --> ParseFlags["Parse Flags & CLI"]
+ ParseFlags --> SetupRegistry["Registry & Plugin Initialization"]
+ SetupRegistry --> ModeCheck{{"Shell / Daemon / Extension?"}}
+
+ ModeCheck -->|"Shell"| ShellInit["Shell Initialization"]
+ ModeCheck -->|"Daemon"| DaemonInit["Daemon Initialization"]
+ ModeCheck -->|"Extension"| ExtInit["Extension Initialization"]
+
+ ShellInit --> StartRuntime["Initializer.start()"]
+ DaemonInit --> StartRuntime
+ ExtInit --> StartRuntime
+
+ StartRuntime --> LoadConfig["Load Config Plugin"]
+ LoadConfig --> ActivateLogger["Activate Logger Plugin"]
+ ActivateLogger --> ActivateDistributed["Activate Distributed Plugin"]
+ ActivateDistributed --> AttachEvents["Attach Event Subscribers"]
+ AttachEvents --> Running["Runtime Active"]
+
+ Running -->|"Signal / Error"| ShutdownReq["requestShutdown()"]
+ ShutdownReq --> Graceful["Dispatcher Stop & Join"]
+ Graceful --> AlarmGuard["AlarmRunnable Guard"]
+ AlarmGuard --> Exit["Process Exit"]
diff --git a/docs/diagrams/architecture/database-and-storage-plugins-2.mmd b/docs/diagrams/architecture/database-and-storage-plugins-2.mmd
deleted file mode 100644
index 605504b8b71..00000000000
--- a/docs/diagrams/architecture/database-and-storage-plugins-2.mmd
+++ /dev/null
@@ -1,4 +0,0 @@
-flowchart TD
- DB["EphemeralDatabasePlugin"] --> Map["std::map>"]
- Map --> DomainMap["Domain Map"]
- DomainMap --> KeyValue["boost::variant"]
diff --git a/docs/diagrams/architecture/database-and-storage-plugins-3.mmd b/docs/diagrams/architecture/database-and-storage-plugins-3.mmd
deleted file mode 100644
index cea2ef35f02..00000000000
--- a/docs/diagrams/architecture/database-and-storage-plugins-3.mmd
+++ /dev/null
@@ -1,6 +0,0 @@
-flowchart TD
- Start["Startup"] --> CheckFlag{{"disable_database?"}}
- CheckFlag -->|"No"| UseRocksDB["Activate RocksDB Plugin"]
- CheckFlag -->|"Yes"| UseEphemeral["Activate Ephemeral Plugin"]
- UseRocksDB --> InitDone["Database Initialized"]
- UseEphemeral --> InitDone
diff --git a/docs/diagrams/architecture/database-and-storage-plugins-4.mmd b/docs/diagrams/architecture/database-and-storage-plugins-4.mmd
deleted file mode 100644
index 721f5928c67..00000000000
--- a/docs/diagrams/architecture/database-and-storage-plugins-4.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- ResetCall["resetDatabase()"] --> LockWrite["Acquire Write Lock"]
- LockWrite --> TearDown["Plugin tearDown()"]
- TearDown --> SetUp["Plugin setUp()"]
- SetUp --> Unlock["Release Lock"]
diff --git a/docs/diagrams/architecture/database-and-storage-plugins-5.mmd b/docs/diagrams/architecture/database-and-storage-plugins-5.mmd
deleted file mode 100644
index eed79ca554a..00000000000
--- a/docs/diagrams/architecture/database-and-storage-plugins-5.mmd
+++ /dev/null
@@ -1,6 +0,0 @@
-flowchart TD
- ReadVersion["Read results_version"] --> Compare["Compare with target version"]
- Compare -->|"Older"| RunMigration["Execute migrateVxVy()"]
- RunMigration --> UpdateVersion["Persist new version"]
- UpdateVersion --> Compare
- Compare -->|"Match"| Done["Migration Complete"]
diff --git a/docs/diagrams/architecture/database-and-storage-plugins.mmd b/docs/diagrams/architecture/database-and-storage-plugins.mmd
deleted file mode 100644
index a4efc77fa93..00000000000
--- a/docs/diagrams/architecture/database-and-storage-plugins.mmd
+++ /dev/null
@@ -1,19 +0,0 @@
-flowchart TD
- CoreModules["Core And Feature Modules"] --> DBInterface["IDatabaseInterface"]
- DBInterface --> OsqueryDB["OsqueryDatabase"]
- OsqueryDB --> RegistryLayer["Database Plugin Registry"]
- RegistryLayer --> RocksDBPlugin["RocksDB Plugin (Persistent)"]
- RegistryLayer --> EphemeralPlugin["Ephemeral Database Plugin (In-Memory)"]
-
- subgraph storage_domains["Logical Storage Domains"]
- PersistentSettings["configurations"]
- Queries["queries"]
- Events["events"]
- Logs["logs"]
- Carves["carves"]
- Distributed["distributed"]
- QueryPerformance["query_performance"]
- end
-
- RocksDBPlugin --> storage_domains
- EphemeralPlugin --> storage_domains
diff --git a/docs/diagrams/architecture/database-backend-2.mmd b/docs/diagrams/architecture/database-backend-2.mmd
new file mode 100644
index 00000000000..ea3265df9e4
--- /dev/null
+++ b/docs/diagrams/architecture/database-backend-2.mmd
@@ -0,0 +1,8 @@
+flowchart TD
+ Start["Process Startup"] --> Init["initDatabasePlugin()"]
+ Init --> CheckDisable{"disable_database flag?"}
+ CheckDisable -->|"Yes"| UseEphemeral["Set Active Plugin: Ephemeral"]
+ CheckDisable -->|"No"| UseRocksDB["Set Active Plugin: RocksDB"]
+ UseEphemeral --> MarkInit["kDBInitialized = true"]
+ UseRocksDB --> MarkInit
+ MarkInit --> Ready["Database Ready"]
diff --git a/docs/diagrams/architecture/database-backend-3.mmd b/docs/diagrams/architecture/database-backend-3.mmd
new file mode 100644
index 00000000000..933143948d2
--- /dev/null
+++ b/docs/diagrams/architecture/database-backend-3.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ Caller["Higher Level Module"] --> Helper["getDatabaseValue()"]
+ Helper --> Lock["Acquire Read Lock"]
+ Lock --> Plugin["Active DatabasePlugin"]
+ Plugin --> Result["Return Status and Value"]
diff --git a/docs/diagrams/architecture/database-backend-4.mmd b/docs/diagrams/architecture/database-backend-4.mmd
new file mode 100644
index 00000000000..ccf661641c7
--- /dev/null
+++ b/docs/diagrams/architecture/database-backend-4.mmd
@@ -0,0 +1,5 @@
+flowchart LR
+ Client["Component Using IDatabaseInterface"] --> Interface["IDatabaseInterface"]
+ Interface --> OsqueryDB["OsqueryDatabase"]
+ OsqueryDB --> GlobalHelpers["Global Database Helpers"]
+ GlobalHelpers --> ActivePlugin["Active DatabasePlugin"]
diff --git a/docs/diagrams/architecture/database-backend-5.mmd b/docs/diagrams/architecture/database-backend-5.mmd
new file mode 100644
index 00000000000..7b0d1612c78
--- /dev/null
+++ b/docs/diagrams/architecture/database-backend-5.mmd
@@ -0,0 +1,3 @@
+flowchart TD
+ DB["Ephemeral DB"] --> DomainMap["Map<Domain, Map<Key, Value>>"]
+ DomainMap --> KeyValue["Key -> Variant(int or string)"]
diff --git a/docs/diagrams/architecture/database-backend-6.mmd b/docs/diagrams/architecture/database-backend-6.mmd
new file mode 100644
index 00000000000..6de7e0315f0
--- /dev/null
+++ b/docs/diagrams/architecture/database-backend-6.mmd
@@ -0,0 +1,6 @@
+flowchart TD
+ ResetCall["resetDatabase()"] --> RegistryCall["Registry::call action=reset"]
+ RegistryCall --> WriteLock["Acquire Write Lock"]
+ WriteLock --> TearDown["Plugin tearDown()"]
+ TearDown --> SetUp["Plugin setUp()"]
+ SetUp --> Done["Database Reinitialized"]
diff --git a/docs/diagrams/architecture/database-backend-7.mmd b/docs/diagrams/architecture/database-backend-7.mmd
new file mode 100644
index 00000000000..e84462568b4
--- /dev/null
+++ b/docs/diagrams/architecture/database-backend-7.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ Start["upgradeDatabase(target)"] --> ReadVersion["Read results_version"]
+ ReadVersion --> Compare{"Current != Target?"}
+ Compare -->|"Yes"| Migrate["Run Migration Step"]
+ Migrate --> UpdateVersion["Persist New Version"]
+ UpdateVersion --> Compare
+ Compare -->|"No"| Done["Upgrade Complete"]
diff --git a/docs/diagrams/architecture/database-backend.mmd b/docs/diagrams/architecture/database-backend.mmd
new file mode 100644
index 00000000000..8d428609973
--- /dev/null
+++ b/docs/diagrams/architecture/database-backend.mmd
@@ -0,0 +1,11 @@
+flowchart TD
+ CoreRuntime["Core Runtime and Lifecycle"] --> DatabaseBackend["Database Backend"]
+
+ DatabaseBackend --> Registry["Registry Factory"]
+ DatabaseBackend --> RocksDBPlugin["RocksDB Plugin"]
+ DatabaseBackend --> EphemeralPlugin["Ephemeral Database Plugin"]
+
+ DatabaseBackend --> ConfigModule["Configuration and Packs"]
+ DatabaseBackend --> LoggingModule["Logging and Query Metadata"]
+ DatabaseBackend --> DistributedModule["Distributed Querying"]
+ DatabaseBackend --> EventsModule["Events Core and Subscriptions"]
diff --git a/docs/diagrams/architecture/distributed-querying-2.mmd b/docs/diagrams/architecture/distributed-querying-2.mmd
index af1e3628736..9a1e365a4b4 100644
--- a/docs/diagrams/architecture/distributed-querying-2.mmd
+++ b/docs/diagrams/architecture/distributed-querying-2.mmd
@@ -1,11 +1,8 @@
flowchart TD
- Start["Pull Updates"] --> Accept["acceptWork()"]
- Accept --> Pending{"Pending Queries?"}
- Pending -->|"Yes"| Run["runQueries()"]
- Run --> Deny{"Denylisted?"}
- Deny -->|"No"| Execute["Execute via SQL Engine"]
- Execute --> Record["recordQueryPerformance()"]
- Record --> Queue["addResult()"]
- Queue --> Flush["flushCompleted()"]
- Deny -->|"Yes"| Skip["Skip Execution"]
- Flush --> End["Cycle Complete"]
+ Start["Start Loop"] --> Pull["pullUpdates()"]
+ Pull --> Check["Pending Queries?"]
+ Check -->|"Yes"| Run["runQueries()"]
+ Check -->|"No"| Sleep["Wait Interval"]
+ Run --> Flush["flushCompleted()"]
+ Flush --> Sleep
+ Sleep --> Pull
diff --git a/docs/diagrams/architecture/distributed-querying-3.mmd b/docs/diagrams/architecture/distributed-querying-3.mmd
index 2850535d935..e573649ebb8 100644
--- a/docs/diagrams/architecture/distributed-querying-3.mmd
+++ b/docs/diagrams/architecture/distributed-querying-3.mmd
@@ -1,6 +1,7 @@
flowchart TD
- Incoming["Incoming Query"] --> Check["checkAndSetAsRunning()"]
- Check --> Running{"Already Running?"}
- Running -->|"Within Duration"| Block["Denylisted"]
- Running -->|"Expired"| Allow["Allow Execution"]
- Check -->|"First Time"| Allow
+ ReceiveWork["acceptWork()"] --> HasDiscovery["Has Discovery Query?"]
+ HasDiscovery -->|"No"| Enqueue["Enqueue Query"]
+ HasDiscovery -->|"Yes"| RunDiscovery["Execute Discovery"]
+ RunDiscovery --> DiscoveryResult["Rows Returned?"]
+ DiscoveryResult -->|"Yes"| Enqueue
+ DiscoveryResult -->|"No"| Skip["Skip Query"]
diff --git a/docs/diagrams/architecture/distributed-querying-4.mmd b/docs/diagrams/architecture/distributed-querying-4.mmd
index da9275ef2f4..f6217cbf1da 100644
--- a/docs/diagrams/architecture/distributed-querying-4.mmd
+++ b/docs/diagrams/architecture/distributed-querying-4.mmd
@@ -1,11 +1,7 @@
-sequenceDiagram
- participant Node
- participant TLS as "TLS Distributed Plugin"
- participant Server
-
- Node->>TLS: pullUpdates()
- TLS->>Server: POST read endpoint
- Server->>TLS: JSON queries
- TLS->>Node: return JSON
- Node->>TLS: writeResults(JSON)
- TLS->>Server: POST write endpoint
+flowchart TD
+ Execute["runQueries()"] --> CheckRun["checkAndSetAsRunning"]
+ CheckRun -->|"Already Running"| WithinWindow["Within Denylist Duration?"]
+ WithinWindow -->|"Yes"| Skip["Skip Execution"]
+ WithinWindow -->|"No"| ExecuteQuery["Execute Query"]
+ CheckRun -->|"Not Running"| ExecuteQuery
+ ExecuteQuery --> Complete["setAsNotRunning"]
diff --git a/docs/diagrams/architecture/distributed-querying-5.mmd b/docs/diagrams/architecture/distributed-querying-5.mmd
new file mode 100644
index 00000000000..63ba0fbdd40
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-querying-5.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ RunQuery["Execute SQL"] --> Measure["Measure Duration"]
+ Measure --> CountRows["Count Result Rows"]
+ CountRows --> Record["recordQueryPerformance"]
+ Record --> Store["Performance Map"]
diff --git a/docs/diagrams/architecture/distributed-querying-6.mmd b/docs/diagrams/architecture/distributed-querying-6.mmd
new file mode 100644
index 00000000000..49b3b814b91
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-querying-6.mmd
@@ -0,0 +1,6 @@
+flowchart TD
+ AddResult["addResult()"] --> Buffer["results_ Vector"]
+ Buffer --> FlushCall["flushCompleted()"]
+ FlushCall --> Serialize["serializeResults()"]
+ Serialize --> PluginWrite["DistributedPlugin.writeResults()"]
+ PluginWrite --> Clear["Clear results_"]
diff --git a/docs/diagrams/architecture/distributed-querying-7.mmd b/docs/diagrams/architecture/distributed-querying-7.mmd
new file mode 100644
index 00000000000..716f98275d1
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-querying-7.mmd
@@ -0,0 +1,11 @@
+flowchart TD
+ Server["Remote Server"] --> PluginPull["getQueries()"]
+ PluginPull --> Accept["acceptWork()"]
+ Accept --> Queue["Internal Queue"]
+ Queue --> Execute["runQueries()"]
+ Execute --> SQL["SQL Engine"]
+ SQL --> Results["DistributedQueryResult"]
+ Results --> Buffer["results_"]
+ Buffer --> Flush["flushCompleted()"]
+ Flush --> PluginPush["writeResults()"]
+ PluginPush --> Server
diff --git a/docs/diagrams/architecture/distributed-querying.mmd b/docs/diagrams/architecture/distributed-querying.mmd
index c57619110a1..939864f9ad9 100644
--- a/docs/diagrams/architecture/distributed-querying.mmd
+++ b/docs/diagrams/architecture/distributed-querying.mmd
@@ -1,10 +1,9 @@
flowchart TD
- Server["Central Server"] -->|"HTTPS"| TLSPlugin["TLS Distributed Plugin"]
- TLSPlugin -->|"getQueries()"| DistributedCore["Distributed Core"]
- DistributedCore -->|"runQueries()"| SQLEngine["SQL Engine"]
- SQLEngine -->|"QueryData"| DistributedCore
- DistributedCore -->|"writeResults()"| TLSPlugin
- TLSPlugin -->|"HTTPS"| Server
-
- DistributedCore -->|"recordQueryPerformance"| Observability["Query Observability"]
- DistributedCore -->|"running state"| Storage["Database Plugins"]
+ RemoteService["Remote Service"] --> DistributedPlugin["Distributed Plugin"]
+ DistributedPlugin --> DistributedManager["Distributed"]
+ DistributedManager --> SQLExecutor["SQL Engine"]
+ SQLExecutor --> VirtualTables["Virtual Tables"]
+ DistributedManager --> DatabaseState["Database Backend"]
+ DistributedManager --> PerformanceTracker["Query Performance"]
+ DistributedManager --> ResultSerializer["Result Serialization"]
+ ResultSerializer --> DistributedPlugin
diff --git a/docs/diagrams/architecture/distributed-tls-plugin-2.mmd b/docs/diagrams/architecture/distributed-tls-plugin-2.mmd
new file mode 100644
index 00000000000..2a1a3bd6768
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-tls-plugin-2.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ Start["Start setUp()"] --> ReadFlag["Read distributed_tls_read_endpoint"]
+ ReadFlag --> MakeReadURI["TLSRequestHelper makeURI()"]
+ MakeReadURI --> WriteFlag["Read distributed_tls_write_endpoint"]
+ WriteFlag --> MakeWriteURI["TLSRequestHelper makeURI()"]
+ MakeWriteURI --> StoreURIs["Store read_uri and write_uri"]
+ StoreURIs --> EndNode["END"]
diff --git a/docs/diagrams/architecture/distributed-tls-plugin-3.mmd b/docs/diagrams/architecture/distributed-tls-plugin-3.mmd
new file mode 100644
index 00000000000..5b740a2a0a5
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-tls-plugin-3.mmd
@@ -0,0 +1,11 @@
+sequenceDiagram
+ participant Engine
+ participant TLSPlugin
+ participant TLSTransport
+ participant Remote
+ Engine->>TLSPlugin: getQueries()
+ TLSPlugin->>TLSTransport: go(JSONSerializer)
+ TLSTransport->>Remote: HTTPS POST read_uri
+ Remote-->>TLSTransport: JSON query payload
+ TLSTransport-->>TLSPlugin: Serialized JSON
+ TLSPlugin-->>Engine: Query JSON
diff --git a/docs/diagrams/architecture/distributed-tls-plugin-4.mmd b/docs/diagrams/architecture/distributed-tls-plugin-4.mmd
new file mode 100644
index 00000000000..008d01437df
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-tls-plugin-4.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ StartWrite["Start writeResults()"] --> ParseJSON["Parse input JSON"]
+ ParseJSON --> ValidCheck{{"Valid JSON?"}}
+ ValidCheck -->|"No"| ReturnError["Return error Status"]
+ ValidCheck -->|"Yes"| SendTLS["TLSRequestHelper go()"]
+ SendTLS --> IgnoreResp["Ignore server response"]
+ IgnoreResp --> EndWrite["END"]
diff --git a/docs/diagrams/architecture/distributed-tls-plugin-5.mmd b/docs/diagrams/architecture/distributed-tls-plugin-5.mmd
new file mode 100644
index 00000000000..79aa8fbf773
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-tls-plugin-5.mmd
@@ -0,0 +1,5 @@
+flowchart LR
+ Scheduler["Distributed Scheduler"] --> Request["DistributedQueryRequest"]
+ Request --> TLSPlugin["Distributed Tls Plugin"]
+ TLSPlugin --> Result["DistributedQueryResult"]
+ Result --> Scheduler
diff --git a/docs/diagrams/architecture/distributed-tls-plugin-6.mmd b/docs/diagrams/architecture/distributed-tls-plugin-6.mmd
new file mode 100644
index 00000000000..7cb156ea3bb
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-tls-plugin-6.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ StartRetry["Start TLS request"] --> Attempt["Attempt HTTPS call"]
+ Attempt --> SuccessCheck{{"Success?"}}
+ SuccessCheck -->|"Yes"| ReturnOK["Return Status OK"]
+ SuccessCheck -->|"No"| RetryCheck{{"Attempts left?"}}
+ RetryCheck -->|"Yes"| Attempt
+ RetryCheck -->|"No"| ReturnFail["Return Status Error"]
diff --git a/docs/diagrams/architecture/distributed-tls-plugin-7.mmd b/docs/diagrams/architecture/distributed-tls-plugin-7.mmd
new file mode 100644
index 00000000000..6a38fad3127
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-tls-plugin-7.mmd
@@ -0,0 +1,3 @@
+flowchart LR
+ Registry["Registry"] --> DistributedCategory["distributed Category"]
+ DistributedCategory --> TLSPlugin["tls Plugin"]
diff --git a/docs/diagrams/architecture/distributed-tls-plugin.mmd b/docs/diagrams/architecture/distributed-tls-plugin.mmd
new file mode 100644
index 00000000000..7e0bf65e6e8
--- /dev/null
+++ b/docs/diagrams/architecture/distributed-tls-plugin.mmd
@@ -0,0 +1,5 @@
+flowchart LR
+ DistributedEngine["Distributed Query Engine"] -->|"getQueries()"| TLSPlugin["Distributed Tls Plugin"]
+ TLSPlugin -->|"HTTPS POST"| RemoteServer["Remote TLS Server"]
+ RemoteServer -->|"JSON Queries"| TLSPlugin
+ TLSPlugin -->|"writeResults()"| DistributedEngine
diff --git a/docs/diagrams/architecture/eventing-framework-and-subscriptions-2.mmd b/docs/diagrams/architecture/eventing-framework-and-subscriptions-2.mmd
deleted file mode 100644
index 0f4dd5e4690..00000000000
--- a/docs/diagrams/architecture/eventing-framework-and-subscriptions-2.mmd
+++ /dev/null
@@ -1,7 +0,0 @@
-flowchart TD
- RegisterSub["registerEventSubscriber()"] --> SetupSub["setUp()"]
- SetupSub --> InitSub["init()"]
- InitSub --> RunningSub["EVENT_RUNNING"]
-
- RegisterPub["registerEventPublisher()"] --> SetupPub["setUp()"]
- SetupPub --> ReadyPub["EVENT_SETUP"]
diff --git a/docs/diagrams/architecture/eventing-framework-and-subscriptions-3.mmd b/docs/diagrams/architecture/eventing-framework-and-subscriptions-3.mmd
deleted file mode 100644
index 22c93bf1ac5..00000000000
--- a/docs/diagrams/architecture/eventing-framework-and-subscriptions-3.mmd
+++ /dev/null
@@ -1,7 +0,0 @@
-flowchart TD
- Delay["delay()"] --> ThreadSpawn["spawn thread per publisher"]
- ThreadSpawn --> RunLoop["run(type_id)"]
- RunLoop --> PublisherRun["publisher->run()"]
- PublisherRun --> Pause["pause(200ms)"]
- Pause --> RunLoop
- RunLoop -->|"isEnding()"| TearDown["tearDown()"]
diff --git a/docs/diagrams/architecture/eventing-framework-and-subscriptions-4.mmd b/docs/diagrams/architecture/eventing-framework-and-subscriptions-4.mmd
deleted file mode 100644
index 13f5eab16f8..00000000000
--- a/docs/diagrams/architecture/eventing-framework-and-subscriptions-4.mmd
+++ /dev/null
@@ -1,7 +0,0 @@
-flowchart TD
- Callback["EventCallback"] --> AddBatch["addBatch()"]
- AddBatch --> AssignID["generateEventIdentifier()"]
- AssignID --> Persist["Database write"]
- Persist --> IndexUpdate["update time index"]
-
- ExpireCheck["expireEventBatches()"] --> RemoveOld["delete expired batches"]
diff --git a/docs/diagrams/architecture/eventing-framework-and-subscriptions-5.mmd b/docs/diagrams/architecture/eventing-framework-and-subscriptions-5.mmd
deleted file mode 100644
index e165a93a604..00000000000
--- a/docs/diagrams/architecture/eventing-framework-and-subscriptions-5.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- SQLQuery["SELECT * FROM example_events"] --> GenTable["genTable()"]
- GenTable --> GenerateRows["generateRows()"]
- GenerateRows --> FilterTime["apply start/stop window"]
- FilterTime --> YieldRows["yield Row to SQL engine"]
diff --git a/docs/diagrams/architecture/eventing-framework-and-subscriptions-6.mmd b/docs/diagrams/architecture/eventing-framework-and-subscriptions-6.mmd
deleted file mode 100644
index 2de3bd7f42b..00000000000
--- a/docs/diagrams/architecture/eventing-framework-and-subscriptions-6.mmd
+++ /dev/null
@@ -1,7 +0,0 @@
-flowchart LR
- FactoryLock["factory_lock_"] --> ProtectPub["event_pubs_"]
- FactoryLock --> ProtectSub["event_subs_"]
-
- SubscriberLock1["event_id_lock_"] --> IDGen["EventID generation"]
- SubscriberLock2["event_record_lock_"] --> RecordWrite["record time bins"]
- SubscriberLock3["event_query_record_"] --> QueryTracking["query usage tracking"]
diff --git a/docs/diagrams/architecture/eventing-framework-and-subscriptions-7.mmd b/docs/diagrams/architecture/eventing-framework-and-subscriptions-7.mmd
deleted file mode 100644
index 58804b2f0a6..00000000000
--- a/docs/diagrams/architecture/eventing-framework-and-subscriptions-7.mmd
+++ /dev/null
@@ -1,16 +0,0 @@
-sequenceDiagram
- participant Config
- participant Factory as EventFactory
- participant Pub as EventPublisher
- participant Sub as EventSubscriber
- participant DB as Database
- participant SQL
-
- Config->>Factory: configUpdate()
- Factory->>Sub: setMinExpiry()
- Factory->>Pub: spawn run loop
- Pub->>Sub: fire event (callback)
- Sub->>DB: addBatch()
- SQL->>Sub: SELECT from event table
- Sub->>DB: generateRows()
- Sub->>SQL: yield rows
diff --git a/docs/diagrams/architecture/eventing-framework-and-subscriptions.mmd b/docs/diagrams/architecture/eventing-framework-and-subscriptions.mmd
deleted file mode 100644
index 169b0f41f29..00000000000
--- a/docs/diagrams/architecture/eventing-framework-and-subscriptions.mmd
+++ /dev/null
@@ -1,9 +0,0 @@
-flowchart TD
- Config["Configuration And Packs"] -->|"scheduled queries"| EventFactory["EventFactory"]
- EventFactory -->|"registers"| Publisher["EventPublisherPlugin"]
- EventFactory -->|"registers"| Subscriber["EventSubscriberPlugin"]
- Subscriber -->|"creates"| SubscriptionObj["Subscription"]
- Publisher -->|"dispatches"| Callback["EventCallback"]
- Callback -->|"addBatch()"| Storage["Database And Storage Plugins"]
- SQL["SQL Engine And Virtual Tables"] -->|"SELECT from _events tables"| Subscriber
- Subscriber -->|"generateRows()"| SQL
diff --git a/docs/diagrams/architecture/events-core-and-subscriptions-2.mmd b/docs/diagrams/architecture/events-core-and-subscriptions-2.mmd
new file mode 100644
index 00000000000..b61aad6bc2e
--- /dev/null
+++ b/docs/diagrams/architecture/events-core-and-subscriptions-2.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ RegisterSub["registerEventSubscriber()"] --> Setup["setUp()"]
+ Setup --> Init["init()"]
+ Init --> Running["EVENT_RUNNING"]
+
+ RegisterPub["registerEventPublisher()"] --> PubSetup["publisher.setUp()"]
+ PubSetup --> Stored["stored in factory map"]
diff --git a/docs/diagrams/architecture/events-core-and-subscriptions-3.mmd b/docs/diagrams/architecture/events-core-and-subscriptions-3.mmd
new file mode 100644
index 00000000000..a302d003aee
--- /dev/null
+++ b/docs/diagrams/architecture/events-core-and-subscriptions-3.mmd
@@ -0,0 +1,6 @@
+flowchart TD
+ Delay["EventFactory.delay()"] --> Spawn["spawn thread per publisher"]
+ Spawn --> RunLoop["EventFactory.run(type)"]
+ RunLoop --> Loop["publisher.run() loop"]
+ Loop --> Pause["pause 200ms"]
+ Loop -->|"error"| TearDown["tearDown()"]
diff --git a/docs/diagrams/architecture/events-core-and-subscriptions-4.mmd b/docs/diagrams/architecture/events-core-and-subscriptions-4.mmd
new file mode 100644
index 00000000000..f56d012279f
--- /dev/null
+++ b/docs/diagrams/architecture/events-core-and-subscriptions-4.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ Context["Context"] --> Namespace["database_namespace"]
+ Context --> Index["event_index"]
+ Context --> LastTime["last_query_time"]
+ Context --> LastEvent["last_event_id"]
diff --git a/docs/diagrams/architecture/events-core-and-subscriptions-5.mmd b/docs/diagrams/architecture/events-core-and-subscriptions-5.mmd
new file mode 100644
index 00000000000..e292f00a045
--- /dev/null
+++ b/docs/diagrams/architecture/events-core-and-subscriptions-5.mmd
@@ -0,0 +1,4 @@
+flowchart TD
+ Publisher["EventPublisher"] --> Callback["EventCallback"]
+ Callback --> AddBatch["addBatch(rows)"]
+ AddBatch --> DBWrite["Database Backend"]
diff --git a/docs/diagrams/architecture/events-core-and-subscriptions-6.mmd b/docs/diagrams/architecture/events-core-and-subscriptions-6.mmd
new file mode 100644
index 00000000000..906f5ac8095
--- /dev/null
+++ b/docs/diagrams/architecture/events-core-and-subscriptions-6.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ SQLQuery["SELECT * FROM event_table"] --> GenTable["genTable()"]
+ GenTable --> GenerateRows["generateRows()"]
+ GenerateRows --> Filter["time window filtering"]
+ Filter --> Yield["RowYield callback"]
diff --git a/docs/diagrams/architecture/events-core-and-subscriptions-7.mmd b/docs/diagrams/architecture/events-core-and-subscriptions-7.mmd
new file mode 100644
index 00000000000..25723ef1def
--- /dev/null
+++ b/docs/diagrams/architecture/events-core-and-subscriptions-7.mmd
@@ -0,0 +1,4 @@
+flowchart LR
+ Sub["EventSubscriber"] -->|"creates"| Subscription
+ Subscription -->|"context + callback"| Publisher
+ Publisher -->|"fires"| Callback
diff --git a/docs/diagrams/architecture/events-core-and-subscriptions-8.mmd b/docs/diagrams/architecture/events-core-and-subscriptions-8.mmd
new file mode 100644
index 00000000000..63776ff8a38
--- /dev/null
+++ b/docs/diagrams/architecture/events-core-and-subscriptions-8.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ Scheduled["Scheduled Queries"] --> Scan["scan for event tables"]
+ Scan --> Compute["compute max interval + count"]
+ Compute --> SetExpiry["setMinExpiry()"]
+ SetExpiry --> ResetCount["resetQueryCount()"]
diff --git a/docs/diagrams/architecture/events-core-and-subscriptions-9.mmd b/docs/diagrams/architecture/events-core-and-subscriptions-9.mmd
new file mode 100644
index 00000000000..cfe73edd0be
--- /dev/null
+++ b/docs/diagrams/architecture/events-core-and-subscriptions-9.mmd
@@ -0,0 +1,8 @@
+flowchart TD
+ Start["Startup"] --> Register["Register Publishers & Subscribers"]
+ Register --> Config["Apply Config Enable/Disable"]
+ Config --> Delay["Spawn Publisher Threads"]
+ Delay --> Running["Event Loop Running"]
+ Running --> Query["SQL Query Execution"]
+ Query --> Expire["Expiration & Optimization"]
+ Expire --> Shutdown["EventFactory.end()"]
diff --git a/docs/diagrams/architecture/events-core-and-subscriptions.mmd b/docs/diagrams/architecture/events-core-and-subscriptions.mmd
new file mode 100644
index 00000000000..3598c240e1c
--- /dev/null
+++ b/docs/diagrams/architecture/events-core-and-subscriptions.mmd
@@ -0,0 +1,20 @@
+flowchart TD
+ Config["Configuration And Packs"] -->|"scheduled queries"| EventFactory["EventFactory"]
+
+ subgraph publishers["Event Publishers"]
+ Pub1["EventPublisherPlugin"]
+ end
+
+ subgraph subscribers["Event Subscribers"]
+ Sub1["EventSubscriberPlugin"]
+ end
+
+ EventFactory -->|"register"| Pub1
+ EventFactory -->|"register"| Sub1
+
+ Sub1 -->|"create"| Subscription["Subscription"]
+ Subscription -->|"attach"| Pub1
+
+ Pub1 -->|"fires events"| Sub1
+ Sub1 -->|"persist rows"| DB["Database Backend"]
+ Sub1 -->|"expose table"| SQL["SQL Engine And Virtual Tables"]
diff --git a/docs/diagrams/architecture/extensions-and-ipc-2.mmd b/docs/diagrams/architecture/extensions-and-ipc-2.mmd
deleted file mode 100644
index 566b1b1c48c..00000000000
--- a/docs/diagrams/architecture/extensions-and-ipc-2.mmd
+++ /dev/null
@@ -1,7 +0,0 @@
-flowchart TD
- Client["ExtensionClient"] --> Transport["Thrift Transport"]
- Transport --> Socket["UNIX Socket or Named Pipe"]
- Socket --> Server["ExtensionRunner or ManagerRunner"]
- Server --> Handler["ExtensionHandler or ExtensionManagerHandler"]
- Handler --> Interface["ExtensionInterface / ExtensionManagerInterface"]
- Interface --> Registry["RegistryFactory"]
diff --git a/docs/diagrams/architecture/extensions-and-ipc-3.mmd b/docs/diagrams/architecture/extensions-and-ipc-3.mmd
deleted file mode 100644
index 9aabee40835..00000000000
--- a/docs/diagrams/architecture/extensions-and-ipc-3.mmd
+++ /dev/null
@@ -1,10 +0,0 @@
-sequenceDiagram
- participant Ext as Extension Process
- participant EM as Extension Manager
- participant Reg as RegistryFactory
-
- Ext->>EM: registerExtension(info, registry)
- EM->>EM: Validate name uniqueness
- EM->>EM: Check SDK compatibility
- EM->>Reg: addBroadcast(uuid, registry)
- EM-->>Ext: Return UUID
diff --git a/docs/diagrams/architecture/extensions-and-ipc-4.mmd b/docs/diagrams/architecture/extensions-and-ipc-4.mmd
deleted file mode 100644
index 642a20aeb10..00000000000
--- a/docs/diagrams/architecture/extensions-and-ipc-4.mmd
+++ /dev/null
@@ -1,4 +0,0 @@
-flowchart LR
- SQL["SQL Engine"] --> ExternalSQL["ExternalSQLPlugin"]
- ExternalSQL --> ManagerClient["ExtensionManagerClient"]
- ManagerClient --> Extension["Extension Process"]
diff --git a/docs/diagrams/architecture/extensions-and-ipc-5.mmd b/docs/diagrams/architecture/extensions-and-ipc-5.mmd
deleted file mode 100644
index a4a24d258ed..00000000000
--- a/docs/diagrams/architecture/extensions-and-ipc-5.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- Watcher["ExtensionManagerWatcher"] --> UUIDs["Registered UUIDs"]
- UUIDs --> Ping["Ping Extension"]
- Ping -->|"Success"| Keep["Keep Registered"]
- Ping -->|"Failure x2"| Remove["Remove Broadcast Route"]
diff --git a/docs/diagrams/architecture/extensions-and-ipc-6.mmd b/docs/diagrams/architecture/extensions-and-ipc-6.mmd
deleted file mode 100644
index 1844fc82272..00000000000
--- a/docs/diagrams/architecture/extensions-and-ipc-6.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- Start["Core Start"] --> StartManager["startExtensionManager()"]
- StartManager --> Watcher["ExtensionManagerWatcher"]
- Watcher --> Runner["ExtensionManagerRunner"]
- Runner --> Listen["Thrift Listen"]
diff --git a/docs/diagrams/architecture/extensions-and-ipc-7.mmd b/docs/diagrams/architecture/extensions-and-ipc-7.mmd
deleted file mode 100644
index 82e492bb100..00000000000
--- a/docs/diagrams/architecture/extensions-and-ipc-7.mmd
+++ /dev/null
@@ -1,6 +0,0 @@
-flowchart TD
- ExtStart["Extension Binary Start"] --> Connect["Connect to Manager Socket"]
- Connect --> Register["registerExtension()"]
- Register --> UUID["Receive UUID"]
- UUID --> StartServer["Start ExtensionRunner"]
- StartServer --> Serve["Serve Thrift Requests"]
diff --git a/docs/diagrams/architecture/extensions-and-ipc.mmd b/docs/diagrams/architecture/extensions-and-ipc.mmd
deleted file mode 100644
index 343a33e6b65..00000000000
--- a/docs/diagrams/architecture/extensions-and-ipc.mmd
+++ /dev/null
@@ -1,12 +0,0 @@
-flowchart LR
- Core["osquery Core"] -->|"Starts"| Manager["Extension Manager"]
- Manager -->|"Registers routes"| Registry["RegistryFactory"]
-
- ExtensionProc["Extension Process"] -->|"registerExtension()"| Manager
- Manager -->|"Assign UUID"| ExtensionProc
-
- Core -->|"callExtension()"| Manager
- Manager -->|"Route to UUID"| ExtensionProc
-
- ExtensionProc -->|"Response"| Manager
- Manager -->|"PluginResponse"| Core
diff --git a/docs/diagrams/architecture/extensions-framework-2.mmd b/docs/diagrams/architecture/extensions-framework-2.mmd
new file mode 100644
index 00000000000..ec4abee316d
--- /dev/null
+++ b/docs/diagrams/architecture/extensions-framework-2.mmd
@@ -0,0 +1,5 @@
+flowchart LR
+ Ext["Extension Process"] -->|"registerExtension"| EM["ExtensionManagerInterface"]
+ EM --> UUID["Assign RouteUUID"]
+ EM --> Registry["RegistryFactory.addBroadcast"]
+ EM --> Store["Store ExtensionInfo"]
diff --git a/docs/diagrams/architecture/extensions-framework-3.mmd b/docs/diagrams/architecture/extensions-framework-3.mmd
new file mode 100644
index 00000000000..4a33447d53d
--- /dev/null
+++ b/docs/diagrams/architecture/extensions-framework-3.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ Client["ExtensionClient"] --> Socket["UNIX Socket / Named Pipe"]
+ Socket --> ThriftServer["TThreadedServer"]
+ ThriftServer --> Handler["ExtensionHandler or ExtensionManagerHandler"]
+ Handler --> Interface["ExtensionInterface Logic"]
diff --git a/docs/diagrams/architecture/extensions-framework-4.mmd b/docs/diagrams/architecture/extensions-framework-4.mmd
new file mode 100644
index 00000000000..9d44736668b
--- /dev/null
+++ b/docs/diagrams/architecture/extensions-framework-4.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ Start["startExtensionManager"] --> Check["Check socketExists"]
+ Check --> Watcher["Start ExtensionManagerWatcher"]
+ Watcher --> Runner["Start ExtensionManagerRunner"]
+ Runner --> Ready["Manager Listening"]
diff --git a/docs/diagrams/architecture/extensions-framework-5.mmd b/docs/diagrams/architecture/extensions-framework-5.mmd
new file mode 100644
index 00000000000..ca43ee332c5
--- /dev/null
+++ b/docs/diagrams/architecture/extensions-framework-5.mmd
@@ -0,0 +1,6 @@
+flowchart TD
+ ExtStart["Extension startExtension"] --> Wait["extensionPathActive"]
+ Wait --> Register["registerExtension"]
+ Register --> UUID["Receive RouteUUID"]
+ UUID --> Watcher["Start ExtensionWatcher"]
+ Watcher --> Runner["Start ExtensionRunner"]
diff --git a/docs/diagrams/architecture/extensions-framework-6.mmd b/docs/diagrams/architecture/extensions-framework-6.mmd
new file mode 100644
index 00000000000..a6a39233e65
--- /dev/null
+++ b/docs/diagrams/architecture/extensions-framework-6.mmd
@@ -0,0 +1,4 @@
+flowchart LR
+ ManagerWatcher["ExtensionManagerWatcher"] --> PingExt["Ping Extension"]
+ PingExt -->|"Success"| Healthy["Keep Registered"]
+ PingExt -->|"Failure x2"| Remove["removeBroadcast(uuid)"]
diff --git a/docs/diagrams/architecture/extensions-framework-7.mmd b/docs/diagrams/architecture/extensions-framework-7.mmd
new file mode 100644
index 00000000000..d2f32cfee44
--- /dev/null
+++ b/docs/diagrams/architecture/extensions-framework-7.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ CoreCall["RegistryFactory.call"] --> Resolve["Resolve RouteUUID"]
+ Resolve --> IPC["callExtension()"]
+ IPC --> Socket["Thrift RPC"]
+ Socket --> ExtHandler["ExtensionHandler.call"]
+ ExtHandler --> Plugin["Local Plugin Execution"]
+ Plugin --> Response["Return PluginResponse"]
diff --git a/docs/diagrams/architecture/extensions-framework.mmd b/docs/diagrams/architecture/extensions-framework.mmd
new file mode 100644
index 00000000000..1e2d8b3aa13
--- /dev/null
+++ b/docs/diagrams/architecture/extensions-framework.mmd
@@ -0,0 +1,12 @@
+flowchart TD
+ Core["osquery Core"] --> Manager["Extension Manager"]
+ Manager --> Registry["RegistryFactory"]
+
+ ExtensionA["Extension Process A"] -->|"registerExtension()"| Manager
+ ExtensionB["Extension Process B"] -->|"registerExtension()"| Manager
+
+ Core -->|"callExtension()"| ExtensionA
+ Core -->|"callExtension()"| ExtensionB
+
+ Manager -->|"health checks"| ExtensionA
+ Manager -->|"health checks"| ExtensionB
diff --git a/docs/diagrams/architecture/filesystem-and-fileops-core-2.mmd b/docs/diagrams/architecture/filesystem-and-fileops-core-2.mmd
new file mode 100644
index 00000000000..ee7ab355e54
--- /dev/null
+++ b/docs/diagrams/architecture/filesystem-and-fileops-core-2.mmd
@@ -0,0 +1,6 @@
+flowchart TD
+ Create["Create PlatformFile"] --> Open["Open Native Handle"]
+ Open --> Valid{"Valid Handle?"}
+ Valid -->|Yes| Operate["Read or Write or Seek"]
+ Valid -->|No| Error["Return Failure"]
+ Operate --> Close["Destructor Closes Handle"]
diff --git a/docs/diagrams/architecture/filesystem-and-fileops-core-3.mmd b/docs/diagrams/architecture/filesystem-and-fileops-core-3.mmd
new file mode 100644
index 00000000000..522761208c3
--- /dev/null
+++ b/docs/diagrams/architecture/filesystem-and-fileops-core-3.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ Pattern["Input Pattern"] --> Normalize["Canonicalize Base Path"]
+ Normalize --> Expand["Apply Wildcards"]
+ Expand --> DetectLoop{"Symlink Loop?"}
+ DetectLoop -->|Yes| Stop["Stop Recursion"]
+ DetectLoop -->|No| Recurse["Continue Expansion"]
+ Recurse --> Filter["Apply Folder or File Filter"]
diff --git a/docs/diagrams/architecture/filesystem-and-fileops-core-4.mmd b/docs/diagrams/architecture/filesystem-and-fileops-core-4.mmd
new file mode 100644
index 00000000000..6a2705e5f8f
--- /dev/null
+++ b/docs/diagrams/architecture/filesystem-and-fileops-core-4.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ Caller["Caller"] --> PF["PlatformFile"]
+ PF --> OSCheck{"Operating System"}
+ OSCheck -->|POSIX| POSIXIO["open read write lseek"]
+ OSCheck -->|Windows| WINIO["CreateFile ReadFile WriteFile"]
+ POSIXIO --> Result["Normalized Result"]
+ WINIO --> Result
diff --git a/docs/diagrams/architecture/filesystem-and-fileops-core.mmd b/docs/diagrams/architecture/filesystem-and-fileops-core.mmd
new file mode 100644
index 00000000000..8c585216854
--- /dev/null
+++ b/docs/diagrams/architecture/filesystem-and-fileops-core.mmd
@@ -0,0 +1,14 @@
+flowchart TD
+ HighLevel["High-Level Consumers"] --> FilesystemAPI["Filesystem API"]
+ FilesystemAPI --> PlatformFile["PlatformFile"]
+ FilesystemAPI --> GlobEngine["Glob and Pattern Resolver"]
+ FilesystemAPI --> PermissionChecks["Permission and Safety Checks"]
+
+ PlatformFile --> PosixImpl["POSIX Implementation"]
+ PlatformFile --> WindowsImpl["Windows Implementation"]
+
+ GlobEngine --> PosixGlob["POSIX glob()"]
+ GlobEngine --> WindowsGlob["Windows FindFirstFile"]
+
+ PermissionChecks --> PosixPerms["POSIX chmod and stat"]
+ PermissionChecks --> WindowsACL["Windows ACL and SID Logic"]
diff --git a/docs/diagrams/architecture/filesystem-and-path-utilities-2.mmd b/docs/diagrams/architecture/filesystem-and-path-utilities-2.mmd
deleted file mode 100644
index 58aae8b080a..00000000000
--- a/docs/diagrams/architecture/filesystem-and-path-utilities-2.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- Open["Open PlatformFile"] --> Validate["Handle Valid?"]
- Validate -->|No| Fail["Return Error"]
- Validate -->|Yes| IO["Read / Write / Seek"]
- IO --> Close["Destructor Closes Handle"]
diff --git a/docs/diagrams/architecture/filesystem-and-path-utilities-3.mmd b/docs/diagrams/architecture/filesystem-and-path-utilities-3.mmd
deleted file mode 100644
index 26f4fd78970..00000000000
--- a/docs/diagrams/architecture/filesystem-and-path-utilities-3.mmd
+++ /dev/null
@@ -1,4 +0,0 @@
-flowchart LR
- Path["File Path"] --> StatCall["platformStat()"]
- StatCall -->|POSIX| POSIXStat["struct stat"]
- StatCall -->|Windows| WinStat["WINDOWS_STAT"]
diff --git a/docs/diagrams/architecture/filesystem-and-path-utilities-4.mmd b/docs/diagrams/architecture/filesystem-and-path-utilities-4.mmd
deleted file mode 100644
index 8f8a50b070d..00000000000
--- a/docs/diagrams/architecture/filesystem-and-path-utilities-4.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- Pattern["Input Pattern"] --> Normalize["replaceGlobWildcards()"]
- Normalize --> Expand["platformGlob()"]
- Expand --> Filter["Apply GLOB_FILES / GLOB_FOLDERS"]
- Filter --> Results["Resolved Paths"]
diff --git a/docs/diagrams/architecture/filesystem-and-path-utilities-5.mmd b/docs/diagrams/architecture/filesystem-and-path-utilities-5.mmd
deleted file mode 100644
index 9efad4a8202..00000000000
--- a/docs/diagrams/architecture/filesystem-and-path-utilities-5.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- ReadCall["readFile()"] --> Open["PlatformFile"]
- Open --> SizeCheck["checkFileReadLimit()"]
- SizeCheck --> Loop["Block Read Loop"]
- Loop --> Predicate["Callback / Buffer"]
diff --git a/docs/diagrams/architecture/filesystem-and-path-utilities-6.mmd b/docs/diagrams/architecture/filesystem-and-path-utilities-6.mmd
deleted file mode 100644
index 8b63dd13550..00000000000
--- a/docs/diagrams/architecture/filesystem-and-path-utilities-6.mmd
+++ /dev/null
@@ -1,3 +0,0 @@
-flowchart LR
- getMounted["getMountedFilesystems()"] --> MountInfo["MountInformation"]
- MountInfo --> StatFS["StatFsInfo"]
diff --git a/docs/diagrams/architecture/filesystem-and-path-utilities-7.mmd b/docs/diagrams/architecture/filesystem-and-path-utilities-7.mmd
deleted file mode 100644
index 60fca930f80..00000000000
--- a/docs/diagrams/architecture/filesystem-and-path-utilities-7.mmd
+++ /dev/null
@@ -1,4 +0,0 @@
-flowchart TD
- Proc["/proc"] --> Enumerate["procEnumerateProcesses()"]
- Enumerate --> FDEnum["procEnumerateProcessDescriptors()"]
- FDEnum --> SocketMap["SocketInodeToProcessInfoMap"]
diff --git a/docs/diagrams/architecture/filesystem-and-path-utilities-8.mmd b/docs/diagrams/architecture/filesystem-and-path-utilities-8.mmd
deleted file mode 100644
index 1359e2b787f..00000000000
--- a/docs/diagrams/architecture/filesystem-and-path-utilities-8.mmd
+++ /dev/null
@@ -1,9 +0,0 @@
-flowchart TD
- File["Candidate File"] --> Exists["Exists?"]
- Exists -->|No| Reject["Reject"]
- Exists --> Owner["Owner Root or Current User?"]
- Owner -->|No| Reject
- Owner --> Writable["World Writable?"]
- Writable -->|Yes| Reject
- Writable --> Exec["Executable Required?"]
- Exec --> Accept["Safe"]
diff --git a/docs/diagrams/architecture/filesystem-and-path-utilities.mmd b/docs/diagrams/architecture/filesystem-and-path-utilities.mmd
deleted file mode 100644
index 44c2abfbebc..00000000000
--- a/docs/diagrams/architecture/filesystem-and-path-utilities.mmd
+++ /dev/null
@@ -1,21 +0,0 @@
-flowchart TD
- Caller["Core / SQL / Extensions"] --> FSAPI["Filesystem API"]
-
- subgraph abstraction_layer["Cross-Platform Abstraction"]
- FSAPI --> PlatformFile["PlatformFile"]
- FSAPI --> Glob["platformGlob()"]
- FSAPI --> Perms["platformChmod()"]
- FSAPI --> Access["platformAccess()"]
- FSAPI --> Stat["platformStat() / lstat()"]
- end
-
- subgraph posix_layer["POSIX Implementation"]
- PlatformFile --> POSIXFile["open/read/write/lstat"]
- Glob --> POSIXGlob["glob()"]
- end
-
- subgraph windows_layer["Windows Implementation"]
- PlatformFile --> WinFile["CreateFile / ReadFile"]
- Glob --> WinGlob["FindFirstFileW"]
- Perms --> WinACL["ACL Manipulation"]
- end
diff --git a/docs/diagrams/architecture/logging-and-query-metadata-2.mmd b/docs/diagrams/architecture/logging-and-query-metadata-2.mmd
new file mode 100644
index 00000000000..e6882d71af5
--- /dev/null
+++ b/docs/diagrams/architecture/logging-and-query-metadata-2.mmd
@@ -0,0 +1,7 @@
+flowchart TD
+ Start["Scheduled Query Execution"] --> FetchOld["getPreviousQueryResults()"]
+ FetchOld --> Exec["Execute SQL"]
+ Exec --> Diff["diff(old, new)"]
+ Diff --> Store["saveQueryResults()"]
+ Store --> BuildLog["Construct QueryLogItem"]
+ BuildLog --> End["Emit Log"]
diff --git a/docs/diagrams/architecture/logging-and-query-metadata-3.mmd b/docs/diagrams/architecture/logging-and-query-metadata-3.mmd
new file mode 100644
index 00000000000..bd750be4d45
--- /dev/null
+++ b/docs/diagrams/architecture/logging-and-query-metadata-3.mmd
@@ -0,0 +1,4 @@
+flowchart LR
+ Logger["LoggerPlugin"] -->|"usesLogStatus()"| StatusHandling["Handle Glog Status"]
+ Logger -->|"usesLogEvent()"| EventHandling["Handle Event Forwarding"]
+ Logger -->|"logSnapshot()"| SnapshotHandling["Snapshot Optimization"]
diff --git a/docs/diagrams/architecture/logging-and-query-metadata-4.mmd b/docs/diagrams/architecture/logging-and-query-metadata-4.mmd
new file mode 100644
index 00000000000..e8a3d61c178
--- /dev/null
+++ b/docs/diagrams/architecture/logging-and-query-metadata-4.mmd
@@ -0,0 +1,12 @@
+flowchart TD
+ Config["Configuration And Packs"] --> SchedulerExec["Scheduled Query"]
+ SchedulerExec --> SQLEngine["SQL Engine"]
+ SQLEngine --> QueryState["Query"]
+ QueryState --> DiffLayer["DiffResults"]
+ QueryState --> Perf["QueryPerformance"]
+ DiffLayer --> LogItem["QueryLogItem"]
+ Perf --> LogItem
+ LogItem --> Serializer["JSON Serialization"]
+ Serializer --> Logger["LoggerPlugin"]
+ Logger --> Sink["External Sink"]
+ QueryState --> Database["Database Backend"]
diff --git a/docs/diagrams/architecture/logging-and-query-metadata.mmd b/docs/diagrams/architecture/logging-and-query-metadata.mmd
new file mode 100644
index 00000000000..be37dcd0ffd
--- /dev/null
+++ b/docs/diagrams/architecture/logging-and-query-metadata.mmd
@@ -0,0 +1,9 @@
+flowchart TD
+ Scheduler["Configuration And Packs"] -->|"creates"| ScheduledQuery
+ ScheduledQuery -->|"executes"| SQLEngine["SQL Engine And Virtual Tables"]
+ SQLEngine -->|"returns rows"| QueryLayer["Query"]
+ QueryLayer -->|"computes diff"| DiffResultsNode["DiffResults"]
+ QueryLayer -->|"builds"| QueryLogItemNode["QueryLogItem"]
+ QueryLogItemNode -->|"serialize"| LoggerPluginNode["LoggerPlugin"]
+ LoggerPluginNode -->|"emits"| ExternalSystem["External Logging System"]
+ QueryLayer -->|"store previous"| DatabaseBackend["Database Backend"]
diff --git a/docs/diagrams/architecture/logging-and-query-observability-2.mmd b/docs/diagrams/architecture/logging-and-query-observability-2.mmd
deleted file mode 100644
index 2feabab2fc7..00000000000
--- a/docs/diagrams/architecture/logging-and-query-observability-2.mmd
+++ /dev/null
@@ -1,7 +0,0 @@
-flowchart TD
- Init["System Initialization"] --> Buffer["Buffer Early Status Logs"]
- Buffer --> LoadConfig["Load Configuration"]
- LoadConfig --> Discover["Discover Logger Plugin"]
- Discover --> InitLogger["LoggerPlugin.init()"]
- InitLogger --> Flush["Flush Buffered StatusLogLine Entries"]
- Flush --> Runtime["Runtime Logging"]
diff --git a/docs/diagrams/architecture/logging-and-query-observability-3.mmd b/docs/diagrams/architecture/logging-and-query-observability-3.mmd
deleted file mode 100644
index 7c5a848377e..00000000000
--- a/docs/diagrams/architecture/logging-and-query-observability-3.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart LR
- Old["Previous Results"] --> DiffEngine["diff()"]
- New["Current Results"] --> DiffEngine
- DiffEngine --> Added["Added Rows"]
- DiffEngine --> Removed["Removed Rows"]
diff --git a/docs/diagrams/architecture/logging-and-query-observability-4.mmd b/docs/diagrams/architecture/logging-and-query-observability-4.mmd
deleted file mode 100644
index 93386e9e467..00000000000
--- a/docs/diagrams/architecture/logging-and-query-observability-4.mmd
+++ /dev/null
@@ -1,4 +0,0 @@
-flowchart TD
- Diff["DiffResults"] --> Serialize["serializeDiffResults()"]
- Serialize --> JSONDoc["JSON Document"]
- JSONDoc --> Logger["LoggerPlugin"]
diff --git a/docs/diagrams/architecture/logging-and-query-observability-5.mmd b/docs/diagrams/architecture/logging-and-query-observability-5.mmd
deleted file mode 100644
index 30d12735a02..00000000000
--- a/docs/diagrams/architecture/logging-and-query-observability-5.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- Item["QueryLogItem"] --> JSON1["serializeQueryLogItem()"]
- Item --> JSON2["serializeQueryLogItemJSON()"]
- Item --> Events1["serializeQueryLogItemAsEvents()"]
- Item --> Events2["serializeQueryLogItemAsEventsJSON()"]
diff --git a/docs/diagrams/architecture/logging-and-query-observability-6.mmd b/docs/diagrams/architecture/logging-and-query-observability-6.mmd
deleted file mode 100644
index 99c77b8ea17..00000000000
--- a/docs/diagrams/architecture/logging-and-query-observability-6.mmd
+++ /dev/null
@@ -1,9 +0,0 @@
-flowchart TD
- Config["ScheduledQuery"] --> Exec["SQL Execution"]
- Exec --> Results["QueryDataTyped"]
- Results --> QueryState["Query.addNewResults()"]
- QueryState --> Diff["DiffResults"]
- Diff --> LogItem["QueryLogItem"]
- LogItem --> Serialize["JSON Serialization"]
- Serialize --> Logger["LoggerPlugin"]
- Logger --> Sink["External Log System"]
diff --git a/docs/diagrams/architecture/logging-and-query-observability-7.mmd b/docs/diagrams/architecture/logging-and-query-observability-7.mmd
deleted file mode 100644
index 88b889b3b8e..00000000000
--- a/docs/diagrams/architecture/logging-and-query-observability-7.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-flowchart TD
- SQ["ScheduledQuery snapshot=true"] --> Exec["Execute Query"]
- Exec --> Full["Full Result Set"]
- Full --> LogItem["QueryLogItem isSnapshot=true"]
- LogItem --> Logger["logSnapshot()"]
diff --git a/docs/diagrams/architecture/logging-and-query-observability.mmd b/docs/diagrams/architecture/logging-and-query-observability.mmd
deleted file mode 100644
index 82b06f91f54..00000000000
--- a/docs/diagrams/architecture/logging-and-query-observability.mmd
+++ /dev/null
@@ -1,15 +0,0 @@
-flowchart TD
- Config["Configuration And Packs"] --> Scheduler["Scheduled Query"]
- Scheduler --> SQ["ScheduledQuery Struct"]
- SQ --> QueryObj["Query State Manager"]
- QueryObj --> DB["Database And Storage Plugins"]
-
- QueryObj --> Diff["DiffResults Engine"]
- Diff --> LogItem["QueryLogItem"]
- LogItem --> Serializer["JSON Serialization"]
- Serializer --> Logger["LoggerPlugin"]
-
- StatusLogs["Internal Status Events"] --> StatusLine["StatusLogLine"]
- StatusLine --> Logger
-
- Logger --> External["External Logging Backend"]
diff --git a/docs/diagrams/architecture/osquery-shell-devtooling-2.mmd b/docs/diagrams/architecture/osquery-shell-devtooling-2.mmd
new file mode 100644
index 00000000000..834d4774cf0
--- /dev/null
+++ b/docs/diagrams/architecture/osquery-shell-devtooling-2.mmd
@@ -0,0 +1,10 @@
+flowchart TD
+ A["Read Input Line"] --> B{"Starts With Dot?"}
+ B -->|"Yes"| C["Meta Command Handler"]
+ B -->|"No"| D["Accumulate SQL"]
+ D --> E{"Complete Statement?"}
+ E -->|"No"| A
+ E -->|"Yes"| F["Execute SQL"]
+ F --> G["shell_callback"]
+ G --> H["Render Output Mode"]
+ H --> A
diff --git a/docs/diagrams/architecture/osquery-shell-devtooling-3.mmd b/docs/diagrams/architecture/osquery-shell-devtooling-3.mmd
new file mode 100644
index 00000000000..530e32ff190
--- /dev/null
+++ b/docs/diagrams/architecture/osquery-shell-devtooling-3.mmd
@@ -0,0 +1,11 @@
+classDiagram
+ class callback_data {
+ +int echoOn
+ +int mode
+ +int showHeader
+ +char separator[20]
+ +char nullvalue[20]
+ +FILE* out
+ +sqlite3_stmt* pStmt
+ +prettyprint_data* prettyPrint
+ }
diff --git a/docs/diagrams/architecture/osquery-shell-devtooling-4.mmd b/docs/diagrams/architecture/osquery-shell-devtooling-4.mmd
new file mode 100644
index 00000000000..5d790f5bb66
--- /dev/null
+++ b/docs/diagrams/architecture/osquery-shell-devtooling-4.mmd
@@ -0,0 +1,8 @@
+classDiagram
+ class prettyprint_data {
+ +QueryData results
+ +vector columns
+ +map lengths
+ }
+
+ callback_data --> prettyprint_data
diff --git a/docs/diagrams/architecture/osquery-shell-devtooling-5.mmd b/docs/diagrams/architecture/osquery-shell-devtooling-5.mmd
new file mode 100644
index 00000000000..7f4952e1b8c
--- /dev/null
+++ b/docs/diagrams/architecture/osquery-shell-devtooling-5.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ Start["BEGIN_TIMER"] --> CaptureStart["Capture rusage + Wall Time"]
+ CaptureStart --> Execute["Run Query"]
+ Execute --> CaptureEnd["Capture End rusage"]
+ CaptureEnd --> Print["Print real, user, sys"]
diff --git a/docs/diagrams/architecture/osquery-shell-devtooling-6.mmd b/docs/diagrams/architecture/osquery-shell-devtooling-6.mmd
new file mode 100644
index 00000000000..a6241074696
--- /dev/null
+++ b/docs/diagrams/architecture/osquery-shell-devtooling-6.mmd
@@ -0,0 +1,5 @@
+flowchart LR
+ Query["SQL Query"] --> Check{"Connect Flag Set?"}
+ Check -->|"No"| LocalExec["shell_exec Local"]
+ Check -->|"Yes"| RemoteExec["shell_exec_remote"]
+ RemoteExec --> ExtClient["ExtensionManagerClient"]
diff --git a/docs/diagrams/architecture/osquery-shell-devtooling-7.mmd b/docs/diagrams/architecture/osquery-shell-devtooling-7.mmd
new file mode 100644
index 00000000000..8323c135a2b
--- /dev/null
+++ b/docs/diagrams/architecture/osquery-shell-devtooling-7.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ Input[".command args"] --> Tokenize["Tokenize Arguments"]
+ Tokenize --> Match["Command Switch"]
+ Match --> Execute["Meta Handler Function"]
+ Execute --> Output["Print To Shell"]
diff --git a/docs/diagrams/architecture/osquery-shell-devtooling-8.mmd b/docs/diagrams/architecture/osquery-shell-devtooling-8.mmd
new file mode 100644
index 00000000000..ce5479fad67
--- /dev/null
+++ b/docs/diagrams/architecture/osquery-shell-devtooling-8.mmd
@@ -0,0 +1,5 @@
+flowchart TD
+ Start["Launch With Pack Flag"] --> LoadConfig["Load Packs From Config"]
+ LoadConfig --> Iterate["Iterate Scheduled Queries"]
+ Iterate --> Run["runQuery"]
+ Run --> Output["Formatted Results"]
diff --git a/docs/diagrams/architecture/osquery-shell-devtooling.mmd b/docs/diagrams/architecture/osquery-shell-devtooling.mmd
new file mode 100644
index 00000000000..c5ef8802b28
--- /dev/null
+++ b/docs/diagrams/architecture/osquery-shell-devtooling.mmd
@@ -0,0 +1,13 @@
+flowchart TD
+ User["User Terminal"] --> Shell["Osquery Shell Devtooling"]
+ Shell --> Parser["Meta Command Parser"]
+ Shell --> Executor["SQL Executor"]
+
+ Executor --> SQLite["SQLite Engine"]
+ SQLite --> VTables["Virtual Tables"]
+ VTables --> Registry["Table Registry"]
+
+ Executor --> DBManager["SQLiteDBManager"]
+ Executor --> Extensions["Extension Manager Client"]
+
+ Extensions --> RemoteExt["Remote Extension Socket"]
diff --git a/docs/diagrams/architecture/remote-http-client-2.mmd b/docs/diagrams/architecture/remote-http-client-2.mmd
index 810bffb2210..5a3e5abaccf 100644
--- a/docs/diagrams/architecture/remote-http-client-2.mmd
+++ b/docs/diagrams/architecture/remote-http-client-2.mmd
@@ -1,5 +1,6 @@
flowchart LR
- OldOpts["Current Options"] --> Compare["operator=="]
- NewOpts["New Options"] --> Compare
- Compare -->|"Different"| Reconfigure["Reinitialize Connection"]
- Compare -->|"Same"| Reuse["Reuse Existing Settings"]
+ Options["Client Options"] --> SSL["SSL Configuration"]
+ Options --> Proxy["Proxy Settings"]
+ Options --> Timeout["Timeout Control"]
+ Options --> Redirects["Redirect Handling"]
+ Options --> KeepAlive["Keep Alive"]
diff --git a/docs/diagrams/architecture/remote-http-client-3.mmd b/docs/diagrams/architecture/remote-http-client-3.mmd
index 6445d351559..3afc2ca34cf 100644
--- a/docs/diagrams/architecture/remote-http-client-3.mmd
+++ b/docs/diagrams/architecture/remote-http-client-3.mmd
@@ -1,4 +1,4 @@
flowchart TD
- Response["HTTP_Response"] --> Headers["Headers"]
- Headers --> Iterator["Iterator"]
- Iterator --> Pair["(name, value)"]
+ Request["HTTP Request"] --> URI["URI Parser"]
+ Request --> Headers["Header Injection"]
+ Request --> Protocol["Scheme Detection"]
diff --git a/docs/diagrams/architecture/remote-http-client-4.mmd b/docs/diagrams/architecture/remote-http-client-4.mmd
index 52c275c5be9..ee0bac1f3a3 100644
--- a/docs/diagrams/architecture/remote-http-client-4.mmd
+++ b/docs/diagrams/architecture/remote-http-client-4.mmd
@@ -1,14 +1,4 @@
-sequenceDiagram
- participant Caller
- participant Client
- participant Resolver
- participant Server
-
- Caller->>Client: get(Request)
- Client->>Resolver: async_resolve()
- Resolver-->>Client: endpoints
- Client->>Server: async_connect()
- Client->>Server: async_write(request)
- Server-->>Client: HTTP response
- Client->>Server: async_read()
- Client-->>Caller: Response
+flowchart TD
+ Response["HTTP Response"] --> Status["Status Code"]
+ Response --> Body["Response Body"]
+ Response --> HeaderAccess["Header Iterator"]
diff --git a/docs/diagrams/architecture/remote-http-client-5.mmd b/docs/diagrams/architecture/remote-http-client-5.mmd
index 1f2bd2fd1e2..72a3062d05b 100644
--- a/docs/diagrams/architecture/remote-http-client-5.mmd
+++ b/docs/diagrams/architecture/remote-http-client-5.mmd
@@ -1,6 +1,11 @@
flowchart TD
- Connect["TCP Connect"] --> TLSCheck{"SSL Enabled?"}
- TLSCheck -->|"Yes"| Handshake["TLS Handshake"]
- TLSCheck -->|"No"| Plain["Plain HTTP"]
- Handshake --> Send["Send Request"]
- Plain --> Send
+ Start["Start Request"] --> Init["Initialize HTTP Request"]
+ Init --> Resolve["DNS Resolve"]
+ Resolve --> Connect["TCP Connect"]
+ Connect --> TLSCheck{{"TLS Enabled?"}}
+ TLSCheck -->|"Yes"| Handshake["SSL Handshake"]
+ TLSCheck -->|"No"| Write
+ Handshake --> Write["Async Write"]
+ Write --> Read["Async Read"]
+ Read --> Complete["Post Response Handler"]
+ Complete --> EndNode["END"]
diff --git a/docs/diagrams/architecture/remote-http-client-6.mmd b/docs/diagrams/architecture/remote-http-client-6.mmd
deleted file mode 100644
index 01586684843..00000000000
--- a/docs/diagrams/architecture/remote-http-client-6.mmd
+++ /dev/null
@@ -1,9 +0,0 @@
-flowchart TD
- Start["Start Network Call"] --> Timer["Start Deadline Timer"]
- Timer --> Async["Async Operation"]
- Async --> Complete{"Completed?"}
- Complete -->|"Yes"| CancelTimer["Cancel Timer"]
- Complete -->|"No"| Timeout["Timer Fires"]
- Timeout --> Abort["Abort Socket"]
- CancelTimer --> Return["Return Response"]
- Abort --> Return
diff --git a/docs/diagrams/architecture/remote-http-client.mmd b/docs/diagrams/architecture/remote-http-client.mmd
index f6bb4f64dff..0cd12bdd75f 100644
--- a/docs/diagrams/architecture/remote-http-client.mmd
+++ b/docs/diagrams/architecture/remote-http-client.mmd
@@ -1,13 +1,8 @@
flowchart TD
- Caller["Caller Module"] --> Client["Client"]
- Client --> Options["Client::Options"]
- Client --> Request["HTTP_Request"]
- Client --> Response["HTTP_Response"]
+ ConfigPlugins["Config Plugins"] -->|"Fetch config"| RemoteHttpClient["Remote Http Client"]
+ DistributedTLS["Distributed TLS Plugin"] -->|"Send queries"| RemoteHttpClient
+ DistributedQuerying["Distributed Querying"] -->|"Submit results"| RemoteHttpClient
- Client --> Resolver["TCP Resolver"]
- Client --> Socket["TCP Socket"]
- Client --> TLSSocket["SSL Stream"]
- Client --> Timer["Deadline Timer"]
-
- Request --> URI["URI Parser"]
- Response --> Headers["Header Iterator"]
+ RemoteHttpClient -->|"TCP"| Asio["Boost Asio"]
+ RemoteHttpClient -->|"HTTP"| Beast["Boost Beast"]
+ RemoteHttpClient -->|"TLS"| OpenSSL["OpenSSL"]
diff --git a/docs/diagrams/architecture/sql-engine-and-virtual-tables-2.mmd b/docs/diagrams/architecture/sql-engine-and-virtual-tables-2.mmd
index 09946020084..b4acebdb726 100644
--- a/docs/diagrams/architecture/sql-engine-and-virtual-tables-2.mmd
+++ b/docs/diagrams/architecture/sql-engine-and-virtual-tables-2.mmd
@@ -1,5 +1,9 @@
-flowchart LR
- Caller["Caller"] --> GetConn["SQLiteDBManager.get()"]
- GetConn --> PrimaryCheck{"Primary Available?"}
- PrimaryCheck -->|Yes| Primary["Primary SQLiteDBInstance"]
- PrimaryCheck -->|No| Transient["Transient SQLiteDBInstance"]
+flowchart TD
+ Start["Query Request"] --> GetDB["SQLiteDBManager.get()"]
+ GetDB --> UseCache["Set Cache Mode"]
+ UseCache --> Prepare["sqlite3_prepare_v2"]
+ Prepare --> Step["sqlite3_step"]
+ Step --> Rows["readRows()"]
+ Rows --> Finalize["sqlite3_finalize"]
+ Finalize --> Clear["Clear Affected Tables"]
+ Clear --> End["Return Status + Results"]
diff --git a/docs/diagrams/architecture/sql-engine-and-virtual-tables-3.mmd b/docs/diagrams/architecture/sql-engine-and-virtual-tables-3.mmd
index 6bded7bfd12..ff4c1bd8570 100644
--- a/docs/diagrams/architecture/sql-engine-and-virtual-tables-3.mmd
+++ b/docs/diagrams/architecture/sql-engine-and-virtual-tables-3.mmd
@@ -1,4 +1,7 @@
flowchart TD
- Prepare["sqlite3_prepare_v2"] --> Authorizer["sqliteAuthorizer"]
- Authorizer -->|Allowed| Continue["Execute Statement"]
- Authorizer -->|Denied| Reject["SQLITE_DENY"]
+ Request["get() or getConnection()"] --> CheckPrimary{"Primary DB Exists?"}
+ CheckPrimary -->|"No"| Init["openOptimized()"]
+ CheckPrimary -->|"Yes"| Reuse["Reuse Primary"]
+ Init --> Attach["attachVirtualTables()"]
+ Reuse --> ReturnPrimary["Return Primary or Transient"]
+ Attach --> ReturnPrimary
diff --git a/docs/diagrams/architecture/sql-engine-and-virtual-tables-4.mmd b/docs/diagrams/architecture/sql-engine-and-virtual-tables-4.mmd
index d79fe38ce6a..fc480c5a593 100644
--- a/docs/diagrams/architecture/sql-engine-and-virtual-tables-4.mmd
+++ b/docs/diagrams/architecture/sql-engine-and-virtual-tables-4.mmd
@@ -1,5 +1,9 @@
flowchart TD
- Query["SQL Query"] --> ExplainPlan["EXPLAIN QUERY PLAN"]
- Query --> Explain["EXPLAIN"]
- Explain --> OpcodeMap["kSQLOpcodes Mapping"]
- OpcodeMap --> TypeInference["Apply Column Types"]
+ Create["xCreate or xConnect"] --> Declare["sqlite3_declare_vtab"]
+ Declare --> BestIndex["xBestIndex"]
+ BestIndex --> Filter["xFilter"]
+ Filter --> Next["xNext"]
+ Next --> Column["xColumn"]
+ Column --> Rowid["xRowid"]
+ Rowid --> Eof["xEof"]
+ Eof --> Close["xClose"]
diff --git a/docs/diagrams/architecture/sql-engine-and-virtual-tables-5.mmd b/docs/diagrams/architecture/sql-engine-and-virtual-tables-5.mmd
index 5a569905d36..270bc393296 100644
--- a/docs/diagrams/architecture/sql-engine-and-virtual-tables-5.mmd
+++ b/docs/diagrams/architecture/sql-engine-and-virtual-tables-5.mmd
@@ -1,12 +1,6 @@
-sequenceDiagram
- participant SQLite
- participant Module as "sqlite3_module"
- participant Table as "TablePlugin"
-
- SQLite->>Module: xBestIndex
- Module->>SQLite: Constraint plan
-
- SQLite->>Module: xFilter
- Module->>Table: generate(context)
- Table-->>Module: Row set
- Module-->>SQLite: Rows
+flowchart TD
+ Query["User Query"] --> ExplainPlan["EXPLAIN QUERY PLAN"]
+ ExplainPlan --> Explain["EXPLAIN"]
+ Explain --> Parse["Parse Opcode Rows"]
+ Parse --> ApplyTypes["applyTypes()"]
+ ApplyTypes --> Columns["Typed Column Metadata"]
diff --git a/docs/diagrams/architecture/sql-engine-and-virtual-tables-6.mmd b/docs/diagrams/architecture/sql-engine-and-virtual-tables-6.mmd
deleted file mode 100644
index ebfb533e38c..00000000000
--- a/docs/diagrams/architecture/sql-engine-and-virtual-tables-6.mmd
+++ /dev/null
@@ -1,10 +0,0 @@
-flowchart TD
- Start["Query Submitted"] --> Prepare["sqlite3_prepare_v2"]
- Prepare --> Execute["sqlite3_step Loop"]
- Execute -->|Virtual Table Access| VTab
- VTab --> xBestIndex
- xBestIndex --> xFilter
- xFilter --> Generate["TablePlugin.generate()"]
- Generate --> Rows["Return Rows"]
- Rows --> Finalize["sqlite3_finalize"]
- Finalize --> End["Results Returned"]
diff --git a/docs/diagrams/architecture/sql-engine-and-virtual-tables.mmd b/docs/diagrams/architecture/sql-engine-and-virtual-tables.mmd
index f435ddde934..9a037ea9a38 100644
--- a/docs/diagrams/architecture/sql-engine-and-virtual-tables.mmd
+++ b/docs/diagrams/architecture/sql-engine-and-virtual-tables.mmd
@@ -1,11 +1,8 @@
flowchart TD
- Client["SQL Caller (Scheduler / CLI / Extension)"] --> SQLPlugin["SQLiteSQLPlugin"]
+ Client["SQL Caller\nScheduler, Shell, API"] --> SQLPlugin["SQLiteSQLPlugin"]
SQLPlugin --> DBManager["SQLiteDBManager"]
DBManager --> DBInstance["SQLiteDBInstance"]
- DBInstance --> SQLiteCore[("In-Memory SQLite Engine")]
-
- SQLiteCore --> VTabModule["sqlite3_module (Virtual Table Module)"]
- VTabModule --> VirtualTable["VirtualTable Wrapper"]
- VirtualTable --> TablePlugin["TablePlugin (Registry)"]
-
- SQLiteCore --> Planner["QueryPlanner"]
+ DBInstance --> SQLiteCore[("SQLite Engine")]
+ SQLiteCore --> VTableModule["sqlite3_module\nVirtual Table Layer"]
+ VTableModule --> TablePlugin["TablePlugin\nRegistry"]
+ TablePlugin --> DataSource["System Data Sources\nFilesystem, Processes, Network"]
diff --git a/docs/getting-started/first-steps.md b/docs/getting-started/first-steps.md
index 3b002d66b32..c76f6b8bf25 100644
--- a/docs/getting-started/first-steps.md
+++ b/docs/getting-started/first-steps.md
@@ -1,178 +1,244 @@
# First Steps
-Now that osquery is running, here are the first things to explore and configure.
+Welcome to osquery! This guide walks you through the first five things to do after a successful installation.
---
## 1. Explore Available Tables
-osquery ships with hundreds of virtual tables. Discover them with the `.tables` command in the interactive shell:
+osquery exposes 300+ virtual tables across Linux, macOS, and Windows. Start by discovering what's available in the interactive shell:
```bash
-./build/osquery/osqueryi
+./osquery/osqueryi
```
+List all available tables:
+
+```sql
+.tables
+```
+
+Search for tables matching a keyword:
+
+```sql
+.tables process
+```
+
+Get the schema of a specific table:
+
+```sql
+.schema processes
+```
+
+Expected output:
+
+```text
+CREATE VIRTUAL TABLE processes USING osquery(
+ pid BIGINT,
+ name TEXT,
+ path TEXT,
+ cmdline TEXT,
+ state TEXT,
+ cwd TEXT,
+ root TEXT,
+ uid BIGINT,
+ ...
+);
+```
+
+---
+
+## 2. Run Your First Security Queries
+
+Try these essential security-focused queries:
+
+**Find processes running from unusual locations:**
+
```sql
--- List all available tables
-osquery> .tables
+SELECT pid, name, path
+FROM processes
+WHERE path NOT LIKE '/usr/%'
+ AND path NOT LIKE '/bin/%'
+ AND path NOT LIKE '/sbin/%'
+ AND on_disk = 0;
+```
--- Search for tables by name
-osquery> .tables process
-osquery> .tables network
-osquery> .tables user
+**List all listening network ports:**
--- Inspect the schema of any table
-osquery> .schema processes
-osquery> .schema listening_ports
-osquery> .schema users
+```sql
+SELECT pid, port, protocol, address
+FROM listening_ports
+WHERE address != '127.0.0.1';
```
-Tables are organized by platform:
+**Find recently modified files in system directories:**
-| Category | Example Tables |
-|---|---|
-| **System** | `system_info`, `uptime`, `cpu_info`, `memory_info` |
-| **Processes** | `processes`, `process_open_files`, `process_open_sockets` |
-| **Networking** | `listening_ports`, `interface_addresses`, `arp_cache`, `routes` |
-| **Users & Groups** | `users`, `groups`, `logged_in_users`, `sudoers` |
-| **Packages** | `deb_packages`, `rpm_packages`, `homebrew_packages`, `chocolatey_packages` |
-| **Events** | `file_events`, `process_events`, `socket_events` |
-| **Security** | `authorized_keys`, `certificates`, `secureboot`, `disk_encryption` |
+```sql
+SELECT path, mtime, size
+FROM file
+WHERE directory = '/etc'
+ AND mtime > (SELECT unix_time - 3600 FROM time);
+```
+
+**Check logged-in users:**
+
+```sql
+SELECT username, tty, host, time
+FROM logged_in_users;
+```
---
-## 2. Write Your First Scheduled Query Pack
+## 3. Create Your First Query Pack
-Create a configuration pack to run queries on a schedule:
+Query packs allow you to schedule queries to run at regular intervals. Create a configuration file:
```bash
-sudo tee /etc/osquery/packs/first-steps.json <<'EOF'
+mkdir -p /etc/osquery
+```
+
+```bash
+cat > /etc/osquery/osquery.conf << 'EOF'
{
- "queries": {
- "users_snapshot": {
- "query": "SELECT uid, username, shell, directory FROM users;",
- "interval": 3600,
- "description": "Snapshot of all local users every hour"
+ "options": {
+ "config_plugin": "filesystem",
+ "logger_plugin": "filesystem",
+ "logger_path": "/var/log/osquery",
+ "schedule_splay_percent": 10
+ },
+ "schedule": {
+ "running_processes": {
+ "query": "SELECT pid, name, path, cmdline FROM processes;",
+ "interval": 60,
+ "description": "Track all running processes every minute"
},
- "listening_ports": {
- "query": "SELECT pid, port, protocol, address FROM listening_ports;",
- "interval": 300,
- "description": "Check open ports every 5 minutes"
+ "network_connections": {
+ "query": "SELECT pid, local_address, local_port, remote_address, remote_port FROM process_open_sockets WHERE state = 'ESTABLISHED';",
+ "interval": 30,
+ "description": "Track established network connections every 30 seconds"
},
- "new_processes": {
- "query": "SELECT pid, name, path, cmdline, start_time FROM processes;",
- "interval": 60,
- "description": "Poll running processes every minute"
+ "user_activity": {
+ "query": "SELECT username, tty, host, time FROM logged_in_users;",
+ "interval": 300,
+ "description": "Track user logins every 5 minutes"
}
}
}
EOF
```
-Reference it in your `osquery.conf`:
+Start the daemon with this configuration:
-```json
-{
- "options": {
- "logger_plugin": "filesystem",
- "schedule_splay_percent": 10
- },
- "packs": {
- "first-steps": "/etc/osquery/packs/first-steps.json"
- }
-}
+```bash
+./osquery/osqueryd \
+ --config_path=/etc/osquery/osquery.conf \
+ --pidfile=/var/run/osqueryd.pid \
+ --daemonize=true
```
---
-## 3. Enable File Integrity Monitoring
+## 4. Understand Event-Based Tables
-osquery can monitor filesystem changes using platform-native event APIs (inotify on Linux, FSEvents on macOS, ETW on Windows):
+Some tables capture events in real time rather than querying static state. To enable file integrity monitoring (FIM):
-```json
+Add file paths to watch in your configuration:
+
+```bash
+cat > /etc/osquery/osquery.conf << 'EOF'
{
- "file_paths": {
- "etc": ["/etc/%%"],
- "homes": ["/root/.ssh/%%", "/home/%/.ssh/%%"],
- "sensitive": ["/usr/bin/%%", "/usr/sbin/%%"]
+ "options": {
+ "config_plugin": "filesystem",
+ "logger_plugin": "filesystem",
+ "logger_path": "/var/log/osquery",
+ "disable_events": false
},
"schedule": {
"file_events": {
- "query": "SELECT * FROM file_events;",
+ "query": "SELECT target_path, action, time FROM file_events;",
"interval": 30
}
+ },
+ "file_paths": {
+ "etc": [
+ "/etc/%%"
+ ],
+ "home": [
+ "/home/%/.ssh/%%"
+ ]
}
}
+EOF
```
-Then query the event table:
+Query file events interactively:
```sql
-osquery> SELECT time, target_path, action, md5 FROM file_events;
+SELECT target_path, action, time
+FROM file_events
+ORDER BY time DESC
+LIMIT 20;
```
---
-## 4. Connect to OpenFrame (Flamingo Platform)
-
-If you are part of the [OpenFrame](https://openframe.ai) / [Flamingo](https://flamingo.run) platform:
+## 5. Configure OpenFrame Integration
-1. Obtain your OpenFrame credentials from your platform administrator
-2. Configure the TLS enrollment endpoint in your daemon flags
-3. The `OpenframeAuthorizationManager` handles token lifecycle automatically
-4. The `OpenframeTokenRefresher` keeps sessions active in the background
+To connect this osquery instance with the OpenFrame/Flamingo platform:
-The OpenFrame layer uses AES-256-GCM encryption via the `OpenframeEncryptionService` β all credential handling is fully automated once configured.
+### Obtain Your Token File
-Refer to your environment configuration for the specific connection details.
+After authenticating with the OpenFrame platform, you'll receive an encrypted token file. Store it securely:
----
+```bash
+sudo mkdir -p /etc/openframe
+sudo chmod 700 /etc/openframe
+# Copy your encrypted token file here
+sudo cp openframe-token.enc /etc/openframe/token.enc
+sudo chmod 600 /etc/openframe/token.enc
+```
-## 5. Load an Extension
+### Configure the Token Path
-osquery's extension system lets you add custom tables, loggers, and configuration plugins as separate processes:
+Set the token file path in your osquery configuration:
```bash
-# Start osqueryd with extension support enabled
-sudo ./build/osquery/osqueryd \
- --config_path=/etc/osquery/osquery.conf \
- --extensions_socket=/var/osquery/osquery.em \
- --extensions_autoload=/etc/osquery/extensions.load
-
-# In a separate terminal, run your extension
-./my_extension --socket=/var/osquery/osquery.em
+cat > /etc/osquery/osquery.conf << 'EOF'
+{
+ "options": {
+ "config_plugin": "tls",
+ "logger_plugin": "tls",
+ "tls_hostname": "your-openframe-endpoint.openframe.ai",
+ "enroll_secret_path": "/etc/openframe/token.enc"
+ }
+}
+EOF
```
-Extensions communicate via Apache Thrift over UNIX domain sockets (Linux/macOS) or named pipes (Windows).
+Refer to your OpenFrame environment configuration for the correct hostname and secret key values.
---
-## Key Configuration Flags
+## Key Configuration Options Reference
-| Flag | Description | Default |
-|---|---|---|
-| `--config_path` | Path to the JSON configuration file | Platform-specific |
-| `--logger_plugin` | Logging backend (`filesystem`, `tls`, `syslog`) | `filesystem` |
-| `--schedule_splay_percent` | Random splay to distribute query load | `10` |
-| `--extensions_socket` | Path to the Thrift extension socket | Platform-specific |
-| `--config_refresh` | How often (seconds) to refresh remote config | `0` (disabled) |
-| `--watchdog_level` | Resource limit profile (0=normal, 1=restrictive, -1=disabled) | `0` |
+| Option | Description | Example |
+|--------|-------------|---------|
+| `config_plugin` | Configuration source (`filesystem`, `tls`) | `"filesystem"` |
+| `logger_plugin` | Log destination (`filesystem`, `tls`, `syslog`) | `"filesystem"` |
+| `logger_path` | Directory for filesystem logs | `"/var/log/osquery"` |
+| `schedule_splay_percent` | Random schedule jitter (%) | `10` |
+| `disable_events` | Disable event-based tables | `false` |
+| `config_refresh` | Config refresh interval (seconds) | `60` |
---
## Where to Get Help
| Resource | Link |
-|---|---|
-| **OpenMSP Community Slack** | [Join here](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) |
-| **OpenMSP Website** | [https://www.openmsp.ai/](https://www.openmsp.ai/) |
-| **Flamingo Platform** | [https://flamingo.run](https://flamingo.run) |
-| **OpenFrame** | [https://openframe.ai](https://openframe.ai) |
-
-> All support and discussions are managed on the **OpenMSP Slack community** β not GitHub Issues or GitHub Discussions.
-
----
-
-## Watch: osquery in Action
+|----------|------|
+| **Community Slack** | [OpenMSP](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) |
+| **Flamingo Platform** | [flamingo.run](https://flamingo.run) |
+| **OpenFrame Platform** | [openframe.ai](https://openframe.ai) |
+| **OpenMSP Community** | [openmsp.ai](https://www.openmsp.ai/) |
-[](https://www.youtube.com/watch?v=1UcWGiHbLVo)
+> **Tip:** The OpenMSP Slack community is the primary support channel. GitHub Issues and Discussions are not used for this project.
diff --git a/docs/getting-started/introduction.md b/docs/getting-started/introduction.md
index a15e0308dbb..e0a87137857 100644
--- a/docs/getting-started/introduction.md
+++ b/docs/getting-started/introduction.md
@@ -1,113 +1,169 @@
-# Introduction to osquery with OpenFrame
+# Introduction to osquery
-**osquery** is a cross-platform operating system instrumentation framework that exposes live system state and activity as relational data β enabling you to query your operating system using SQL.
+> **osquery** is a cross-platform operating system instrumentation framework that exposes system state as relational data using SQL. Part of the [Flamingo](https://flamingo.run) / [OpenFrame](https://openframe.ai) platform, this distribution extends the upstream osquery project with OpenFrame-specific authentication, token management, and encryption services.
-Built and extended by the [Flamingo / OpenFrame](https://openframe.ai) platform, this distribution integrates osquery's powerful SQL telemetry engine with OpenFrame's AI-driven MSP automation infrastructure.
+[](https://www.youtube.com/watch?v=bRd3JCJZ1vc)
---
-## What is osquery?
+## What Is osquery?
-osquery transforms every host into a **SQL-queryable telemetry node**. Instead of parsing flat log files or calling proprietary APIs, you write standard SQL queries to explore:
-
-- Running processes and open sockets
-- Installed packages and browser extensions
-- Kernel modules and hardware inventory
-- Filesystem events and user activity
-- Network interfaces and firewall rules
-- Windows Registry, launchd, systemd units, and much more
+osquery lets operators, security teams, and infrastructure engineers **query the operating system as if it were a database**. Instead of parsing log files or writing custom scripts, you write standard SQL:
```sql
--- Which processes are listening on ports?
-SELECT pid, name, port, protocol FROM listening_ports JOIN processes USING (pid);
+SELECT name, pid, path FROM processes WHERE on_disk = 0;
+```
--- What Chrome extensions are installed?
-SELECT u.username, e.name, e.version, e.permissions
-FROM users u, chrome_extensions e
-WHERE e.uid = u.uid;
+```sql
+SELECT address, mac FROM interface_addresses;
```
----
+```sql
+SELECT * FROM users WHERE uid = 0;
+```
-## OpenFrame Integration
+Under the hood, osquery embeds **SQLite** and implements a virtual table layer that maps OS primitives β processes, files, users, network sockets, kernel state, and more β into relational tables queryable in real time.
-This repository extends osquery with the **OpenFrame** authentication and encryption layer:
+---
-- **`OpenframeAuthorizationManager`** β Secure, lifecycle-controlled JWT token management
-- **`OpenframeEncryptionService`** β AES-256-GCM symmetric encryption via OpenSSL
-- **`OpenframeTokenExtractor`** β Token acquisition from OpenFrame services
-- **`OpenframeTokenRefresher`** β Background thread for seamless token renewal
+## Key Features
-These components are part of the [OpenFrame platform](https://www.flamingo.run/openframe) β the unified MSP interface that integrates IT tools under a single AI-driven experience.
+| Feature | Description |
+|---------|-------------|
+| **SQL-based OS querying** | Interact with 300+ virtual tables covering every aspect of the OS |
+| **Cross-platform** | Runs on Linux, macOS, and Windows with a unified interface |
+| **Scheduled queries** | Define query packs that run on a configurable schedule |
+| **Event-driven tables** | Subscribe to OS events (file changes, process launches, network connections) |
+| **Distributed querying** | Push queries to an entire fleet from a central control plane |
+| **Plugin extensions** | Add custom tables, loggers, and config sources without modifying the binary |
+| **OpenFrame integration** | Secure token-based authentication with the OpenFrame/Flamingo platform |
+| **AES-256-GCM encryption** | Built-in encrypted token storage and retrieval |
---
-## Key Features
+## OpenFrame Extensions
-| Feature | Description |
-|---|---|
-| **SQL Querying** | Query live OS data with standard SQL via embedded SQLite |
-| **Virtual Tables** | 300+ platform-specific tables across Linux, macOS, and Windows |
-| **Event Monitoring** | inotify, BPF, FSEvents, ETW, audit β all exposed as queryable tables |
-| **Scheduled Queries** | Pack-based query scheduling with differential result tracking |
-| **Distributed Queries** | Remote SQL orchestration across fleets via TLS |
-| **Extension System** | Runtime plugin model with Apache Thrift IPC |
-| **OpenFrame Auth** | AES-256-GCM encrypted JWT token management for OpenFrame services |
-| **Cross-Platform** | Linux (x86_64, aarch64), macOS, and Windows support |
+This distribution adds the following components on top of upstream osquery:
+
+- **`OpenframeAuthorizationManager`** β Singleton manager for securely storing and retrieving the OpenFrame bearer token used to authenticate with OpenFrame services.
+- **`OpenframeEncryptionService`** β AES-256-GCM encryption/decryption service that secures tokens at rest.
+- **`OpenframeTokenExtractor`** β Reads and decrypts authentication tokens from an encrypted token file on disk.
+- **`OpenframeTokenRefresher`** β Background thread that periodically re-extracts and refreshes the authentication token.
---
## Target Audience
-osquery with OpenFrame is designed for:
+osquery is designed for:
-- **IT Operations Teams** using Flamingo/OpenFrame for managed service delivery
-- **Security Engineers** building detection and response workflows
-- **Fleet Administrators** who need SQL-level visibility across endpoints
-- **Developers** building extensions, plugins, or custom table providers
-- **MSP Technicians** leveraging Mingo AI and Fae automation through the OpenFrame platform
+- **Security engineers** building endpoint detection and response (EDR) capabilities
+- **Infrastructure operators** requiring real-time system observability
+- **MSP technicians** using the Flamingo/OpenFrame platform for managed IT operations
+- **Developers** extending osquery with custom tables and plugins
---
-## Architecture Overview
+## System Architecture Overview
```mermaid
-graph TD
- CLI["osqueryi / osqueryd"] --> Core["Core Init And Runtime"]
- Core --> Config["Configuration And Packs"]
+flowchart TD
+ Core["Core Runtime And Lifecycle"] --> Config["Configuration And Packs"]
Core --> SQL["SQL Engine And Virtual Tables"]
- Core --> Events["Eventing Framework"]
- Core --> Logging["Logging And Observability"]
- Core --> DB["Database And Storage Plugins"]
- Core --> Dist["Distributed Querying"]
- Core --> Ext["Extensions And IPC"]
- Core --> HTTP["Remote HTTP Client"]
- Core --> OF["OpenFrame Auth Layer"]
+ Core --> DB["Database Backend"]
+ Core --> Logging["Logging And Query Metadata"]
+ Core --> Events["Events Core And Subscriptions"]
+ Core --> Extensions["Extensions Framework"]
+ Core --> Distributed["Distributed Querying"]
+
Config --> SQL
Config --> Events
+ Config --> Logging
+
SQL --> Logging
+ SQL --> DB
+
Events --> DB
- Dist --> SQL
- Dist --> HTTP
- Ext --> SQL
- OF --> HTTP
+ Events --> Logging
+
+ Distributed --> SQL
+ Distributed --> DB
+ Distributed --> Logging
+
+ Extensions --> SQL
+ Extensions --> Config
+ Extensions --> Distributed
+
+ OpenFrame["OpenFrame Auth Layer"] --> Core
+```
+
+### Architectural Layers
+
+| Layer | Responsibility |
+|-------|---------------|
+| **Core Runtime** | Bootstrapping, flags, lifecycle, watchdog, shutdown |
+| **SQL Engine** | Query parsing, execution, virtual tables (300+ tables) |
+| **Configuration** | Packs, scheduling, dynamic updates |
+| **Database Backend** | Persistent RocksDB and ephemeral keyβvalue storage |
+| **Logging** | Structured result serialization and emission |
+| **Events** | Real-time event ingestion and exposure as tables |
+| **Distributed** | Remote query retrieval and result submission |
+| **Extensions** | External plugin injection via Thrift IPC |
+| **OpenFrame Auth** | Token lifecycle, AES-256-GCM encryption, background refresh |
+
+---
+
+## Query Execution Flow
+
+```mermaid
+sequenceDiagram
+ participant Scheduler as "Scheduler / Shell"
+ participant SQL as "SQL Engine"
+ participant VTable as "Virtual Tables"
+ participant DB as "Database Backend"
+ participant Logger as "Logger Plugin"
+
+ Scheduler->>SQL: Submit SQL query
+ SQL->>VTable: Execute against virtual tables
+ VTable-->>SQL: Return rows
+ SQL->>DB: Fetch previous results
+ DB-->>SQL: Previous result set
+ SQL->>SQL: Compute diff (added/removed)
+ SQL->>Logger: Emit QueryLogItem
+ Logger-->>Scheduler: Log confirmation
+```
+
+---
+
+## Two Execution Modes
+
+**`osqueryi`** β Interactive shell for ad-hoc queries:
+
+```bash
+osqueryi
+osquery> SELECT name, version FROM os_version;
+```
+
+**`osqueryd`** β Daemon for continuous scheduled execution:
+
+```bash
+osqueryd --config_path=/etc/osquery/osquery.conf
```
---
## Getting Started
-- Review system and software prerequisites in the [Prerequisites Guide](prerequisites.md)
-- Follow the [Quick Start Guide](quick-start.md) to build and run osquery in minutes
-- Explore common workflows in [First Steps](first-steps.md)
+- Review the [Prerequisites](prerequisites.md) guide to ensure your environment is ready.
+- Follow the [Quick Start](quick-start.md) to get osquery running in minutes.
+- Complete [First Steps](first-steps.md) to explore key features and initial configuration.
---
-## Community and Support
+## Community & Support
-osquery with OpenFrame is part of the [Flamingo](https://flamingo.run) open-source ecosystem.
+Join the open MSP community for questions, discussions, and contributions:
-- π¬ **Community Slack**: [OpenMSP Community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA)
-- π **OpenMSP**: [https://www.openmsp.ai/](https://www.openmsp.ai/)
-- π **OpenFrame Platform**: [https://openframe.ai](https://openframe.ai)
-- 𦩠**Flamingo**: [https://flamingo.run](https://flamingo.run)
+- **Slack**: [OpenMSP Community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA)
+- **Platform**: [https://www.openmsp.ai/](https://www.openmsp.ai/)
+- **Flamingo**: [https://flamingo.run](https://flamingo.run)
+- **OpenFrame**: [https://openframe.ai](https://openframe.ai)
diff --git a/docs/getting-started/prerequisites.md b/docs/getting-started/prerequisites.md
index 8e6027a2725..f18a058dde1 100644
--- a/docs/getting-started/prerequisites.md
+++ b/docs/getting-started/prerequisites.md
@@ -1,167 +1,160 @@
# Prerequisites
-Before building or deploying osquery with OpenFrame, ensure your environment meets the requirements below.
+Before building or running this OpenFrame-enhanced distribution of osquery, ensure your system and environment meet the following requirements.
---
## System Requirements
-| Tier | RAM | CPU Cores | Disk Space |
-|---|---|---|---|
-| **Minimum** | 24 GB | 6 cores | 50 GB |
-| **Recommended** | 32 GB | 12 cores | 100 GB |
+| Component | Minimum | Recommended |
+|-----------|---------|-------------|
+| **RAM** | 24 GB | 32 GB |
+| **CPU Cores** | 6 cores | 12 cores |
+| **Disk Space** | 50 GB | 100 GB |
+| **OS** | Linux, macOS, or Windows | Linux (Ubuntu 20.04+) |
-> Building osquery from source is resource-intensive. The recommended configuration significantly reduces build times and prevents out-of-memory failures during compilation.
+> **Note:** The build system compiles osquery and all vendored libraries from source. Insufficient RAM will cause build failures or extremely slow compilation times.
---
## Supported Operating Systems
-| Platform | Architecture | Notes |
-|---|---|---|
-| Linux | x86_64, aarch64 | Ubuntu 20.04+, RHEL 8+, Debian 11+ |
-| macOS | x86_64, aarch64 (Apple Silicon) | macOS 12+ recommended |
-| Windows | x86_64, aarch64 | Windows 10/11, Server 2019+ |
+| OS | Architectures | Notes |
+|----|--------------|-------|
+| **Linux** | x86_64, aarch64 | Ubuntu 20.04+, CentOS 8+, Fedora 34+ |
+| **macOS** | x86_64, aarch64 | macOS 12 (Monterey) or newer |
+| **Windows** | x86_64, aarch64 | Windows 10 / Server 2019 or newer |
---
-## Required Software
+## Required Build Tools
-| Tool | Minimum Version | Purpose |
-|---|---|---|
-| **CMake** | 3.21+ | Build system generator |
-| **Python** | 3.8+ | Code generation, tooling scripts |
-| **Git** | 2.x | Source control |
-| **C++ Compiler** | GCC 9+ / Clang 10+ / MSVC 2019+ | Compiling C++17 sources |
-| **Ninja** | 1.10+ | Fast parallel builds (recommended) |
-| **OpenSSL** | 1.1.1+ | TLS support and AES-256-GCM encryption (OpenFrame) |
+### All Platforms
----
+| Tool | Version | Purpose |
+|------|---------|---------|
+| **CMake** | β₯ 3.21 | Build system generator |
+| **Python 3** | β₯ 3.6 | Code generation scripts |
+| **Git** | β₯ 2.x | Source control |
+| **Clang / GCC** | Clang β₯ 13 or GCC β₯ 10 | C++ compiler (C++17 required) |
-## Optional but Recommended
+### Linux
-| Tool | Purpose |
-|---|---|
-| **ccache** | Speeds up incremental C++ builds significantly |
-| **clang-format** | Code formatting (enforced by CI) |
-| **Docker** | Isolated build environments for Linux targets |
+| Tool | Version | Purpose |
+|------|---------|---------|
+| **Clang** | β₯ 13 | Preferred compiler |
+| **lld** | β₯ 13 | LLVM linker (faster builds) |
+| **build-essential** | β | Base build tools |
+| **libssl-dev** | β₯ 1.1.1 | OpenSSL (required for OpenFrame encryption) |
----
+### macOS
-## Platform-Specific Notes
+| Tool | Version | Purpose |
+|------|---------|---------|
+| **Xcode Command Line Tools** | Latest | Compiler toolchain |
+| **Homebrew** | Latest | Package manager |
-### Linux
+### Windows
-On Debian/Ubuntu, install build essentials:
+| Tool | Version | Purpose |
+|------|---------|---------|
+| **Visual Studio** | 2019 or 2022 | MSVC compiler |
+| **Windows SDK** | β₯ 10.0.18362 | Platform headers |
-```bash
-sudo apt-get update
-sudo apt-get install -y \
- build-essential \
- cmake \
- ninja-build \
- python3 \
- python3-pip \
- git \
- openssl \
- libssl-dev \
- clang-format
-```
+---
-On RHEL/CentOS/Fedora:
+## OpenSSL Requirement
-```bash
-sudo dnf install -y \
- gcc-c++ \
- cmake \
- ninja-build \
- python3 \
- git \
- openssl-devel \
- clang
-```
+The OpenFrame encryption service (`OpenframeEncryptionService`) requires **OpenSSL** with AES-GCM support. This is used for:
-### macOS
+- AES-256-GCM encryption and decryption of authentication tokens
+- Base64 encoding/decoding of encrypted payloads
-Install Xcode Command Line Tools and Homebrew tools:
+Verify OpenSSL is available:
```bash
-xcode-select --install
-brew install cmake ninja python3 openssl git
+openssl version
```
-### Windows
-
-1. Install [Visual Studio 2019 or 2022](https://visualstudio.microsoft.com/) with the **Desktop development with C++** workload
-2. Install [CMake](https://cmake.org/download/) 3.21+
-3. Install [Git for Windows](https://git-scm.com/download/win)
-4. Install [Python 3.8+](https://www.python.org/downloads/windows/)
-5. Optionally install [Ninja](https://github.com/ninja-build/ninja/releases)
-
----
-
-## OpenFrame Platform Requirements
-
-If you are connecting to the [OpenFrame platform](https://openframe.ai), you also need:
+Expected output example:
-| Requirement | Description |
-|---|---|
-| **OpenFrame Account** | Active account on the Flamingo/OpenFrame platform |
-| **Network Access** | Outbound HTTPS (port 443) to OpenFrame services |
-| **AES-256 Key** | Symmetric secret key for the `OpenframeEncryptionService` |
-| **JWT Token** | Authorization token managed by `OpenframeAuthorizationManager` |
-
-Refer to your environment configuration and OpenFrame administrator for credential details.
+```text
+OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
+```
---
-## Environment Variables
+## Node.js / JavaScript Tools (Documentation Pipeline Only)
-The following environment variables may be required depending on your deployment:
+The `package.json` at the repository root lists tooling dependencies for the documentation generation pipeline β these are **not** required to build or run osquery itself:
-| Variable | Purpose |
-|---|---|
-| `OSQUERY_FLAGS_FILE` | Path to a flagfile for osquery runtime configuration |
-| `OSQUERY_EXTENSIONS_SOCKET` | Path to the Thrift extension manager socket |
-| `OSQUERY_CONFIG_PATH` | Custom configuration file path (overrides default) |
+| Package | Purpose |
+|---------|---------|
+| `@voltagent/core` | Documentation agent (pipeline tool) |
+| `@ai-sdk/anthropic` | AI SDK (pipeline tool) |
+| `@anthropic-ai/sdk` | Anthropic SDK (pipeline tool) |
+| `glob` | File globbing (pipeline tool) |
+| `zod` | Schema validation (pipeline tool) |
-Set variables using your shell profile or deployment tooling. For example:
-
-```bash
-export OSQUERY_FLAGS_FILE="/etc/osquery/osquery.flags"
-export OSQUERY_EXTENSIONS_SOCKET="/var/osquery/osquery.em"
-```
+> **Important:** These packages support documentation generation tooling only. They are not runtime or build dependencies for osquery.
---
-## Verifying Your Environment
+## Verification Checklist
-Run the following checks to confirm your build environment is ready:
+Run these commands to verify your environment before starting:
```bash
-# Check CMake version
+# Check CMake version (need >= 3.21)
cmake --version
-# Check C++ compiler
-c++ --version
+# Check Clang version (need >= 13)
+clang --version
-# Check Python
+# Check Python version (need >= 3.6)
python3 --version
# Check Git
git --version
-# Check OpenSSL
+# Check OpenSSL (required for OpenFrame encryption)
openssl version
-# Check Ninja (if installed)
-ninja --version
+# Check disk space (need >= 50 GB free)
+df -h .
+
+# Check available memory (need >= 24 GB)
+free -h
```
-All tools should report versions meeting the minimums in the table above.
+---
+
+## Account and Access Requirements
+
+| Resource | Required For | Notes |
+|----------|-------------|-------|
+| **OpenFrame account** | OpenFrame platform integration | Sign up at [openframe.ai](https://openframe.ai) |
+| **Flamingo account** | MSP platform features | Sign up at [flamingo.run](https://flamingo.run) |
+| **OpenMSP Slack** | Community support | [Join here](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) |
+
+---
+
+## Environment Variables
+
+The following environment variables may be required depending on your build and deployment configuration:
+
+| Variable | Purpose | Required |
+|----------|---------|----------|
+| `OPENFRAME_TOKEN_PATH` | Path to the encrypted OpenFrame token file | For OpenFrame integration |
+| `OPENFRAME_SECRET_KEY` | 256-bit secret key for AES-256-GCM token decryption | For OpenFrame integration |
+
+> **Security Note:** Never hardcode secret keys in shell scripts or configuration files. Use a secrets manager or secure environment injection.
---
## Next Steps
-Once prerequisites are confirmed, proceed to the [Quick Start Guide](quick-start.md) to clone, build, and run osquery.
+Once your environment is verified:
+
+- Follow the [Quick Start](quick-start.md) to build and run osquery in minutes.
+- Complete [First Steps](first-steps.md) to configure your first query packs.
diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md
index 0ab657e8ce7..d67dea47055 100644
--- a/docs/getting-started/quick-start.md
+++ b/docs/getting-started/quick-start.md
@@ -1,170 +1,206 @@
# Quick Start
-Get osquery with OpenFrame running in under 10 minutes.
+Get osquery built and running in minutes with this step-by-step guide.
---
-## TL;DR β Fastest Path
+## TL;DR β 5-Minute Setup
```bash
# 1. Clone the repository
git clone https://github.com/flamingo-stack/osquery.git
cd osquery
-# 2. Configure the build
-cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -G Ninja
+# 2. Create the build directory
+mkdir build && cd build
-# 3. Build osquery (this takes 5β30 minutes depending on hardware)
-cmake --build build --parallel $(nproc)
+# 3. Configure with CMake
+cmake ..
-# 4. Run the interactive shell
-./build/osquery/osqueryi
-```
+# 4. Build osquery
+cmake --build . --parallel $(nproc)
-> **Hardware note**: Building from source requires at minimum 24 GB RAM and 6 CPU cores. See the [Prerequisites Guide](prerequisites.md) for full system requirements.
+# 5. Run the interactive shell
+./osquery/osqueryi
+```
---
-## Step 1: Clone the Repository
+## Step-by-Step Instructions
+
+### 1. Clone the Repository
```bash
git clone https://github.com/flamingo-stack/osquery.git
cd osquery
```
----
-
-## Step 2: Configure the Build
-
-### Linux / macOS
+### 2. Configure the Build
```bash
-cmake -S . -B build \
- -DCMAKE_BUILD_TYPE=RelWithDebInfo \
- -G Ninja
+mkdir build
+cd build
+cmake ..
```
-### Windows (Visual Studio)
+Common CMake options:
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `-DCMAKE_BUILD_TYPE=Release` | `RelWithDebInfo` | Build type (Release/Debug/RelWithDebInfo) |
+| `-DCMAKE_C_COMPILER=clang` | System default | C compiler |
+| `-DCMAKE_CXX_COMPILER=clang++` | System default | C++ compiler |
+| `-DOSQUERY_DISABLE_DATABASE=ON` | OFF | Disable RocksDB (use ephemeral backend) |
+
+Example with explicit Clang:
```bash
-cmake -S . -B build ^
- -DCMAKE_BUILD_TYPE=RelWithDebInfo ^
- -G "Visual Studio 17 2022"
+cmake .. \
+ -DCMAKE_C_COMPILER=clang \
+ -DCMAKE_CXX_COMPILER=clang++ \
+ -DCMAKE_BUILD_TYPE=Release
```
-### Common CMake Options
+### 3. Build
-| Option | Description |
-|---|---|
-| `-DCMAKE_BUILD_TYPE=RelWithDebInfo` | Optimized build with debug symbols (recommended) |
-| `-DCMAKE_BUILD_TYPE=Debug` | Full debug build (slower, larger binaries) |
-| `-DCMAKE_BUILD_TYPE=Release` | Fully optimized production build |
-| `-G Ninja` | Use Ninja for faster parallel builds |
-| `-DOSQUERY_BUILD_TESTS=ON` | Include test suite in the build |
+```bash
+# Use all available CPU cores for parallel compilation
+cmake --build . --parallel $(nproc)
+```
----
+> **Tip:** On a 6-core system, this typically takes 20β40 minutes on first build. Subsequent incremental builds are much faster.
-## Step 3: Build
+### 4. Verify the Build
```bash
-# Linux/macOS β use all available CPU cores
-cmake --build build --parallel $(nproc)
-
-# Windows β use all available CPU cores
-cmake --build build --parallel %NUMBER_OF_PROCESSORS%
+# Check the binaries were produced
+ls -la osquery/osqueryi osquery/osqueryd
```
-The first build downloads and compiles all third-party dependencies. Subsequent builds with `ccache` are significantly faster.
+Expected output:
+
+```text
+-rwxr-xr-x ... osquery/osqueryi
+-rwxr-xr-x ... osquery/osqueryd
+```
---
-## Step 4: Run Your First Query
+## Your First Query
-Launch the osquery interactive shell:
+Launch the interactive shell:
```bash
-./build/osquery/osqueryi
+./osquery/osqueryi
```
-Expected output:
+Try a simple query:
+
+```sql
+SELECT name, version FROM os_version;
+```
+
+Expected output (example on Ubuntu):
```text
-Using a virtual database. Need help, type '.help'
-osquery>
++----------+---------+
+| name | version |
++----------+---------+
+| Ubuntu | 22.04 |
++----------+---------+
```
-Now try your first query:
+Try querying running processes:
```sql
-osquery> SELECT hostname, cpu_brand, physical_memory FROM system_info;
+SELECT pid, name, path FROM processes LIMIT 5;
```
-Example output:
+Try querying network interfaces:
-```text
-+------------------+-------------------------------+------------------+
-| hostname | cpu_brand | physical_memory |
-+------------------+-------------------------------+------------------+
-| my-linux-host | Intel(R) Core(TM) i9-12900K | 34207285248 |
-+------------------+-------------------------------+------------------+
+```sql
+SELECT interface, address, mask FROM interface_addresses;
```
----
-
-## Step 5: Explore More Tables
+List all available tables:
```sql
--- List all running processes
-osquery> SELECT pid, name, cmdline FROM processes LIMIT 10;
-
--- Check listening network ports
-osquery> SELECT pid, port, protocol, address FROM listening_ports LIMIT 10;
+.tables
+```
--- List installed packages (Linux)
-osquery> SELECT name, version, arch FROM deb_packages LIMIT 10;
+Exit the shell:
--- Show users on the system
-osquery> SELECT uid, gid, username, shell FROM users;
+```sql
+.exit
```
---
-## Step 6: Run as a Daemon
+## Running osqueryd (Daemon Mode)
+
+The daemon mode runs scheduled queries continuously using a configuration file.
-To run osquery as a background daemon with scheduled queries:
+Create a minimal configuration file:
```bash
-# Create a basic configuration
-sudo mkdir -p /etc/osquery
-sudo tee /etc/osquery/osquery.conf <<'EOF'
+cat > /tmp/osquery.conf << 'EOF'
{
"options": {
+ "config_plugin": "filesystem",
"logger_plugin": "filesystem",
- "schedule_splay_percent": 10
+ "logger_path": "/tmp/osquery_logs",
+ "disable_logging": false
},
"schedule": {
"system_info": {
- "query": "SELECT hostname, cpu_brand, physical_memory FROM system_info;",
- "interval": 3600
+ "query": "SELECT hostname, cpu_type, physical_memory FROM system_info;",
+ "interval": 60
}
}
}
EOF
+```
+
+Run the daemon:
-# Run the daemon
-sudo ./build/osquery/osqueryd --config_path=/etc/osquery/osquery.conf
+```bash
+./osquery/osqueryd --config_path=/tmp/osquery.conf --pidfile=/tmp/osquery.pid
```
+Check logs:
+
+```bash
+ls /tmp/osquery_logs/
+cat /tmp/osquery_logs/osqueryd.results.log
+```
+
+---
+
+## Windows Installation
+
+On Windows (AMD64), you can download the pre-built CLI:
+
+1. Download: [openframe-cli_windows_amd64.zip](https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_windows_amd64.zip)
+2. Extract the archive
+3. Run the installer following the same steps as other operating systems
+
---
-## Expected Results Summary
+## Expected Build Output
+
+A successful build produces:
+
+```text
+[100%] Built target osqueryi
+[100%] Built target osqueryd
+```
+
+The following binaries are available:
-| Command | What You Should See |
-|---|---|
-| `osqueryi` | Interactive SQL prompt |
-| `SELECT * FROM system_info;` | Host identity, CPU, RAM details |
-| `SELECT * FROM processes LIMIT 5;` | Running process list |
-| `osqueryd` | Daemon starts, logs to `/var/log/osquery/` |
+| Binary | Description |
+|--------|-------------|
+| `osquery/osqueryi` | Interactive SQL shell |
+| `osquery/osqueryd` | Continuous monitoring daemon |
---
@@ -172,6 +208,5 @@ sudo ./build/osquery/osqueryd --config_path=/etc/osquery/osquery.conf
After completing this quick start:
-- Follow the [First Steps Guide](first-steps.md) to explore key features and common workflows
-- Review the [Prerequisites Guide](prerequisites.md) for full system and software requirements
-- Explore the [Development section](../development/README.md) to understand the architecture and contribute
+- Read [First Steps](first-steps.md) to explore key features and configuration options.
+- Review [Prerequisites](prerequisites.md) if you encountered build issues.
diff --git a/docs/reference/architecture/README.md b/docs/reference/architecture/README.md
index d8bef8be03c..7b3540a2a03 100644
--- a/docs/reference/architecture/README.md
+++ b/docs/reference/architecture/README.md
@@ -1,366 +1,412 @@
# osquery Repository Overview
-## 1. Purpose of the Repository
+## Purpose
-**osquery** is a cross-platform operating system instrumentation framework that exposes system state and activity as relational data. It embeds a hardened SQLite engine and represents operating system concepts (processes, files, sockets, users, registry keys, etc.) as **virtual tables**, enabling users to query live system data using SQL.
+**osquery** is a cross-platform operating system instrumentation framework that exposes system state as relational data using **SQL**. It allows operators, security teams, and infrastructure engineers to:
-The repository implements:
+- Query system information (processes, files, users, network, kernel state)
+- Schedule and log queries continuously
+- Collect and persist system events
+- Execute distributed queries from a central control plane
+- Extend functionality dynamically through plugins and extensions
-- A secure in-memory SQL engine
-- A virtual table plugin framework
-- Configuration-driven scheduled querying
-- Differential result logging and observability
-- Distributed query orchestration
-- Event-driven monitoring infrastructure
-- Persistent and ephemeral storage backends
-- Remote HTTP/TLS communication
-- Extension-based runtime plugin model
-
-At a high level, osquery transforms a host into a **SQL-queryable telemetry node** with local and distributed control capabilities.
+At its core, osquery embeds SQLite and implements a virtual table layer that maps operating system primitives into relational tables.
---
-# 2. End-to-End Architecture
+# End-to-End Architecture
-The system is modular and plugin-driven. Below is the full end-to-end architecture across core subsystems.
+osquery is structured as a modular runtime composed of subsystems that cooperate through registries, plugins, and well-defined interfaces.
-## 2.1 System-Level Architecture
+## High-Level System Architecture
```mermaid
flowchart TD
- CLI["osqueryi / osqueryd"] --> Core["Core Init And Runtime"]
-
- Core --> Config["Configuration And Packs"]
+ Core["Core Runtime And Lifecycle"] --> Config["Configuration And Packs"]
Core --> SQL["SQL Engine And Virtual Tables"]
- Core --> Events["Eventing Framework"]
- Core --> Logging["Logging And Observability"]
- Core --> DB["Database And Storage Plugins"]
+ Core --> DB["Database Backend"]
+ Core --> Logging["Logging And Query Metadata"]
+ Core --> Events["Events Core And Subscriptions"]
+ Core --> Extensions["Extensions Framework"]
Core --> Distributed["Distributed Querying"]
- Core --> Extensions["Extensions And IPC"]
- Core --> HTTP["Remote HTTP Client"]
- Core --> FS["Filesystem And Path Utilities"]
Config --> SQL
Config --> Events
+ Config --> Logging
+
SQL --> Logging
+ SQL --> DB
+
Events --> DB
+ Events --> Logging
+
Distributed --> SQL
- Distributed --> HTTP
- Logging --> DB
+ Distributed --> DB
+ Distributed --> Logging
+
Extensions --> SQL
- Extensions --> DB
+ Extensions --> Config
+ Extensions --> Distributed
```
----
+### Architectural Layers
-# 3. Runtime Execution Model
+| Layer | Responsibility |
+|-------|----------------|
+| Core Runtime | Bootstrapping, flags, lifecycle, watchdog, shutdown |
+| SQL Engine | Query parsing, execution, virtual tables |
+| Configuration | Packs, scheduling, dynamic updates |
+| Database Backend | Persistent and ephemeral keyβvalue storage |
+| Logging | Structured result serialization and emission |
+| Events | Real-time event ingestion and exposure as tables |
+| Distributed | Remote query retrieval and result submission |
+| Extensions | External plugin injection via Thrift IPC |
-osquery operates in several runtime modes:
+---
-- **Daemon (`osqueryd`)**
-- **Interactive shell (`osqueryi`)**
-- **Watcher / Worker model**
-- **Extension process**
+# Query Execution Flow
-## Runtime Lifecycle
+This diagram shows how a scheduled or distributed query travels through the system.
```mermaid
flowchart TD
- Start["Process Start"] --> Init["Initializer"]
- Init --> Flags["Parse Flags"]
- Init --> Registry["Initialize Registry"]
- Init --> DBInit["Initialize Database"]
- Init --> ExtMgr["Start Extension Manager"]
- Init --> ConfigLoad["Load Configuration"]
- ConfigLoad --> Schedule["Build Schedule"]
- Schedule --> QueryExec["Execute Queries"]
- QueryExec --> Log["Log Results"]
- Log --> End["Runtime Loop"]
+ Source["Scheduled Or Distributed Query"] --> Scheduler["Configuration And Packs"]
+ Scheduler --> SQLPlugin["SQLiteSQLPlugin"]
+ SQLPlugin --> SQLiteCore["SQLite Engine"]
+ SQLiteCore --> VTables["Virtual Tables"]
+ VTables --> TablePlugins["Table Plugins"]
+
+ SQLiteCore --> QueryState["Query State And Diff"]
+ QueryState --> DB["Database Backend"]
+ QueryState --> Diff["DiffResults"]
+
+ Diff --> LogItem["QueryLogItem"]
+ LogItem --> Logger["Logger Plugin"]
+ Logger --> External["External Logging System"]
```
-The **Core Init And Runtime** module governs this lifecycle and ensures safe startup, resource enforcement (watchdog), and graceful shutdown.
+### Execution Steps
-π Reference:
-`osquery/core` β *Core Init And Runtime*
+1. Query originates from:
+ - Scheduled configuration pack
+ - Distributed remote request
+ - Interactive shell
+2. SQLite engine executes against virtual tables.
+3. Previous results are fetched from the database.
+4. Differential results are computed.
+5. Structured log artifact is built.
+6. Results are serialized and emitted via logger plugins.
---
-# 4. SQL Engine and Virtual Table Layer
+# Event Pipeline
-The SQL engine is built around an in-memory SQLite instance hardened with a strict authorizer. All system data is exposed via dynamically attached **virtual tables** backed by registry plugins.
+Event-based tables follow a publisher/subscriber model.
```mermaid
flowchart TD
- Query["SQL Query"] --> SQLite["SQLite Engine"]
- SQLite --> Module["sqlite3_module"]
- Module --> VirtualTable["VirtualTable Wrapper"]
- VirtualTable --> TablePlugin["TablePlugin"]
- TablePlugin --> OS["Operating System Data"]
- OS --> Rows["Rows Returned"]
+ Publisher["Event Publisher Plugin"] --> Subscriber["EventSubscriberPlugin"]
+ Subscriber --> DB["Database Backend"]
+ Subscriber --> SQLTable["Event Virtual Table"]
+ SQLTable --> Query["SELECT From Event Table"]
+ Query --> Logging["Logging And Query Metadata"]
```
-Key characteristics:
-
-- In-memory execution
-- Strict opcode allowlisting
-- Constraint pushdown
-- Projection optimization
-- Extension-backed writable tables
+### Event Model
-π Reference:
-`osquery/sql` β *Sql Engine And Virtual Tables*
+- Publishers collect OS-level events (e.g., file, process, network).
+- Subscribers transform events into rows.
+- Rows are persisted and indexed.
+- SQL queries retrieve time-bounded results.
+- Expiration is schedule-aware.
---
-# 5. Configuration and Packs
+# Distributed Query Flow
-Configuration defines:
-
-- Scheduled queries
-- Packs (query groups)
-- Decorators
-- File monitoring rules
-- Event subscriptions
-- Logger configuration
-- Runtime options
+Distributed querying enables fleet-wide remote execution.
```mermaid
flowchart TD
- Source["Config Source (File / TLS / Extension)"] --> ConfigCore["Config Singleton"]
- ConfigCore --> Parsers["ConfigParserPlugins"]
- Parsers --> Schedule["Scheduled Queries"]
- Schedule --> Scheduler["Query Scheduler"]
- Scheduler --> SQL["SQL Engine"]
+ Server["Remote Server"] --> TLSPlugin["Distributed TLS Plugin"]
+ TLSPlugin --> DistributedEngine["Distributed Querying"]
+ DistributedEngine --> SQL["SQL Engine"]
+ SQL --> Results["DistributedQueryResult"]
+ Results --> TLSPlugin
+ TLSPlugin --> Server
```
-Supports:
+Key mechanisms:
+
+- Pull-based query retrieval
+- Discovery query filtering
+- SHA-based denylisting
+- Performance tracking
+- Batched result flushing
+
+---
+
+# Core Modules Documentation
+
+Below is a structured overview of the repositoryβs major modules and their documentation paths.
+---
+
+## 1. Core Runtime And Lifecycle
+**Path:** `osquery/core`
+
+Responsible for:
+
+- Process bootstrapping
+- Flag management (`FlagDetail`, `FlagInfo`)
+- Watchdog and worker supervision
+- Plugin activation
+- Signal handling and shutdown (`ShutdownData`)
+- Forced termination guard (`AlarmRunnable`)
+
+This module orchestrates startup, runtime state transitions, and graceful termination.
+
+---
+
+## 2. Configuration And Packs
+**Path:** `osquery/config`
+
+Responsible for:
+
+- Loading configuration via plugins
+- Parsing JSON configs
+- Managing scheduled query packs
+- Discovery logic and sharding
+- Denylisting unstable queries
- Hash-based change detection
-- Background refresh runner
-- Query denylisting
-- Dynamic registry reconfiguration
-π Reference:
-`osquery/config` β *Configuration And Packs*
+Core components:
+
+- `ConfigRefreshRunner`
+- `PackStats`
+- `Schedule`
+
+Acts as the control plane for scheduled execution.
---
-# 6. Eventing Framework
+## 3. SQL Engine And Virtual Tables
+**Path:** `osquery/sql`
-The eventing subsystem provides a publish/subscribe model for event-driven monitoring.
+Implements:
-```mermaid
-flowchart TD
- Publisher["EventPublisher"] --> EventFactory["EventFactory"]
- Subscriber["EventSubscriber"] --> EventFactory
- EventFactory --> Callback["EventCallback"]
- Callback --> Storage["Database Storage"]
- SQL["SELECT *_events"] --> Subscriber
-```
+- Embedded SQLite engine
+- Virtual table integration (`sqlite3_module`)
+- Query planning and type inference
+- Constraint pushdown
+- Security authorizer
-Capabilities:
+Core components:
-- Thread-isolated publishers
-- Time-window indexing
-- Config-driven retention
-- Persistent event buffering
-- Optimized incremental queries
+- `SQLiteSQLPlugin`
+- `SQLiteDBManager`
+- `VirtualTable`
+- `BaseCursor`
-π Reference:
-`osquery/events` β *Eventing Framework And Subscriptions*
+This module turns OS data sources into relational tables.
---
-# 7. Logging and Query Observability
+## 4. Database Backend
+**Path:** `osquery/database`
-osquery converts query executions into structured log artifacts.
+Provides:
-```mermaid
-flowchart TD
- Exec["Query Execution"] --> Diff["DiffResults"]
- Diff --> LogItem["QueryLogItem"]
- LogItem --> Serialize["JSON Serialization"]
- Serialize --> Logger["LoggerPlugin"]
- Logger --> Sink["External Backend"]
-```
+- Pluggable database interface
+- Domain-based keyβvalue storage
+- Persistent RocksDB backend
+- Ephemeral in-memory backend
+- Schema migration framework
-Features:
+Core components:
-- Differential result tracking
-- Snapshot support
-- Structured JSON output
-- Performance telemetry
-- Pluggable logging backends
+- `OsqueryDatabase`
+- `EphemeralDatabasePlugin`
-π Reference:
-`osquery/core` β *Logging And Query Observability*
+Stores query state, performance metrics, configuration, events, and distributed state.
---
-# 8. Database and Storage Plugins
+## 5. Logging And Query Metadata
+**Path:** `osquery/core`
-All persistent state is stored through a pluggable key-value interface.
+Transforms execution results into structured logs:
-```mermaid
-flowchart TD
- Modules["Core Modules"] --> Interface["IDatabaseInterface"]
- Interface --> Plugin["Database Plugin"]
- Plugin --> RocksDB["Persistent Backend"]
- Plugin --> Ephemeral["In-Memory Backend"]
-```
+- `QueryLogItem`
+- `DiffResults`
+- `QueryPerformance`
+- `StatusLogLine`
+
+Handles:
+
+- Snapshot vs differential logging
+- JSON serialization
+- Logger plugin integration
+
+---
+
+## 6. Events Core And Subscriptions
+**Path:** `osquery/events`
-Used for:
+Implements:
-- Query state
-- Event buffers
-- Distributed query tracking
-- Configuration backup
-- Performance metrics
+- Publisher/subscriber event framework
+- Event persistence and indexing
+- Schedule-aware expiration
+- Subscriber context isolation
-π Reference:
-`osquery/database` β *Database And Storage Plugins*
+Core components:
+
+- `Subscription`
+- `GenerateRowsResult`
+- `SubscriberExpirationDetails`
+
+Enables real-time OS monitoring as SQL tables.
---
-# 9. Distributed Querying
+## 7. Extensions Framework
+**Path:** `osquery/extensions`
-Enables centralized orchestration of SQL across fleets.
+Provides:
-```mermaid
-flowchart TD
- Server["Central Server"] --> TLS["TLS Distributed Plugin"]
- TLS --> Core["Distributed Core"]
- Core --> SQL["SQL Engine"]
- SQL --> Results["Results"]
- Results --> TLS
- TLS --> Server
-```
+- Thrift-based IPC
+- Dynamic plugin injection
+- RouteUUID-based routing
+- Extension health monitoring
+- Registry broadcast system
-Includes:
+Core components:
-- Discovery query gating
-- SHA256-based denylisting
-- Execution performance tracking
-- Pluggable transport interface
+- `ExtensionManagerHandler`
+- `ImplExtensionClient`
+- `UuidGenerator`
+- `ExtensionManagerWatcher`
-π Reference:
-`osquery/distributed` β *Distributed Querying*
+Allows external binaries to extend osquery safely.
---
-# 10. Extensions and IPC
+## 8. Distributed Querying
+**Path:** `osquery/distributed`
-osquery supports runtime plugin extensions via Apache Thrift IPC.
+Manages:
-```mermaid
-flowchart LR
- Core["osquery Core"] --> Manager["Extension Manager"]
- Extension["External Extension"] --> Manager
- Manager --> Registry["RegistryFactory"]
- Core --> Extension
-```
+- Pull-based distributed queries
+- Discovery gating
+- Denylisting and expiration
+- Result batching and flushing
-Capabilities:
+Core components:
-- Dynamic table plugins
-- Remote SQL execution
-- UUID-based routing
-- Health monitoring
-- Secure socket validation
+- `DistributedQueryRequest`
+- `DistributedQueryResult`
-π Reference:
-`osquery/extensions` β *Extensions And IPC*
+Acts as the fleet execution engine.
---
-# 11. Remote HTTP Client
+## 9. Remote HTTP Client
+**Path:** `osquery/remote`
-Provides secure HTTP/TLS transport used by:
+Implements:
-- Distributed querying
-- Remote logging
-- Remote configuration plugins
+- Boost.Asio + Boost.Beast HTTP client
+- TLS configuration and validation
+- Timeout handling
+- Proxy support
-```mermaid
-flowchart TD
- Caller["Module"] --> Client["HTTP Client"]
- Client --> TLS["TLS Handshake"]
- TLS --> Remote["Remote Server"]
-```
+Used by distributed and config TLS plugins.
-Built on Boost.Asio and Boost.Beast with strict TLS configuration.
+---
-π Reference:
-`osquery/remote` β *Remote Http Client*
+## 10. Config Plugins
+**Path:** `plugins/config`
+
+Includes:
+
+- `FilesystemConfigPlugin`
+- `OptionsConfigParserPlugin`
+- `ViewsConfigParserPlugin`
+- `DecoratorsConfigParserPlugin`
+
+Transforms raw config into runtime state.
---
-# 12. Filesystem and Path Utilities
+## 11. Distributed TLS Plugin
+**Path:** `plugins/distributed`
-Cross-platform abstraction for:
+Implements secure HTTPS transport for distributed queries.
-- Safe file access
-- Glob resolution
-- Permission enforcement
-- Linux `/proc` inspection
-- Windows ACL and metadata handling
+Core component:
-```mermaid
-flowchart TD
- Caller["Subsystem"] --> FS["Filesystem API"]
- FS --> POSIX["POSIX Implementation"]
- FS --> Windows["Windows Implementation"]
-```
+- `TLSDistributedPlugin`
+
+---
+
+## 12. Filesystem And Fileops Core
+**Path:** `osquery/filesystem`
+
+Provides:
-Security-first design ensures safe extension loading and configuration handling.
+- Cross-platform file abstraction
+- Secure permission validation
+- Globbing and recursive path expansion
+- Portable `stat` implementation
-π Reference:
-`osquery/filesystem` β *Filesystem And Path Utilities*
+Used across config, extensions, logging, and tables.
---
-# 13. Repository Structure Summary
-
-| Module | Path | Responsibility |
-|--------|------|----------------|
-| Core Init And Runtime | `osquery/core` | Process lifecycle, flags, watchdog |
-| Configuration And Packs | `osquery/config` | Scheduled queries, packs, decorators |
-| SQL Engine And Virtual Tables | `osquery/sql` | SQLite engine, virtual table layer |
-| Eventing Framework | `osquery/events` | Publisher/subscriber event system |
-| Logging And Query Observability | `osquery/core` | Result diffing, structured logs |
-| Database And Storage Plugins | `osquery/database` | Persistent state abstraction |
-| Distributed Querying | `osquery/distributed` | Remote fleet orchestration |
-| Extensions And IPC | `osquery/extensions` | Thrift-based runtime extensions |
-| Remote HTTP Client | `osquery/remote` | Secure HTTP/TLS transport |
-| Filesystem And Path Utilities | `osquery/filesystem` | Cross-platform file abstraction |
+## 13. Osquery Shell Devtooling
+**Path:** `osquery/devtools`
+
+Implements `osqueryi` interactive shell:
+
+- SQL execution loop
+- Meta commands
+- Pretty-print formatting
+- Remote extension execution
+- CPU profiling (`rusage`)
+
+Core components:
+
+- `callback_data`
+- `prettyprint_data`
---
-# 14. Architectural Principles
+# Architectural Characteristics
-1. **SQL as a Universal Interface**
-2. **Plugin-Driven Extensibility**
-3. **Security-First Execution (SQLite authorizer + permission checks)**
-4. **In-Memory Analytical Core**
-5. **Config-Driven Behavior**
-6. **Differential Logging Efficiency**
-7. **Distributed Fleet Control**
-8. **Cross-Platform Abstraction Layer**
+- β
SQLite-powered relational abstraction
+- β
Strong plugin and registry model
+- β
Pluggable persistence backend
+- β
Differential logging for efficiency
+- β
Schedule-aware event retention
+- β
Extension-based modularity
+- β
Secure TLS distributed execution
+- β
Cross-platform filesystem abstraction
---
-# 15. Conclusion
+# Conclusion
-The `osquery` repository implements a secure, extensible, SQL-based operating system telemetry platform.
+The **osquery** repository implements a modular, extensible, SQL-based operating system instrumentation platform.
-It combines:
+At runtime, it combines:
-- A hardened SQLite execution engine
-- A virtual table plugin architecture
-- Event-driven monitoring
-- Differential logging
-- Distributed query orchestration
-- Runtime extension via IPC
-- Secure remote communication
+- A secure embedded SQL engine
+- A dynamic configuration and scheduling layer
+- A pluggable storage backend
+- A structured logging pipeline
+- A real-time event system
+- A distributed query execution engine
+- A Thrift-based extension framework
-Together, these modules form a scalable, production-grade system observability framework capable of operating both locally and as part of a centrally managed fleet.
\ No newline at end of file
+Together, these subsystems transform low-level OS primitives into structured, queryable, and remotely orchestratable data β enabling observability, compliance, security monitoring, and fleet-wide introspection at scale.
\ No newline at end of file
diff --git a/docs/reference/architecture/config-plugins/config-plugins.md b/docs/reference/architecture/config-plugins/config-plugins.md
new file mode 100644
index 00000000000..6f9c0a8c0f1
--- /dev/null
+++ b/docs/reference/architecture/config-plugins/config-plugins.md
@@ -0,0 +1,347 @@
+# Config Plugins
+
+The **Config Plugins** module is responsible for sourcing, parsing, transforming, and dynamically updating osquery configuration data. It acts as the bridge between raw configuration inputs (files or remote sources) and the structured runtime state consumed by the core engine.
+
+This module is tightly integrated with:
+
+- [Configuration and Packs](../configuration-and-packs/configuration-and-packs.md) β orchestrates config refresh and pack scheduling
+- [SQL Engine and Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md) β executes decorator and file path queries
+- [Database Backend](../database-backend/database-backend.md) β persists generated views and config state
+- [Events Core and Subscriptions](../events-core-and-subscriptions/events-core-and-subscriptions.md) β consumes parsed event configuration
+- [Logging and Query Metadata](../logging-and-query-metadata/logging-and-query-metadata.md) β enriched by decorators
+
+The Config Plugins module is built around two extension points:
+
+1. **ConfigPlugin** β produces raw configuration blobs (e.g., filesystem, remote, update routing).
+2. **ConfigParserPlugin** β parses specific top-level configuration keys and updates runtime state.
+
+---
+
+## Architecture Overview
+
+```mermaid
+flowchart TD
+ CLI["CLI Flags"] --> FilesystemPlugin["FilesystemConfigPlugin"]
+ FilesystemPlugin --> ConfigCore["Config Core"]
+ UpdatePlugin["UpdateConfigPlugin"] --> ConfigCore
+
+ ConfigCore --> DecoratorsParser["DecoratorsConfigParserPlugin"]
+ ConfigCore --> EventsParser["EventsConfigParserPlugin"]
+ ConfigCore --> FilePathsParser["FilePathsConfigParserPlugin"]
+ ConfigCore --> OptionsParser["OptionsConfigParserPlugin"]
+ ConfigCore --> ViewsParser["ViewsConfigParserPlugin"]
+
+ DecoratorsParser --> SQL["SQL Engine"]
+ FilePathsParser --> SQL
+ ViewsParser --> SQL
+
+ ViewsParser --> DB["Database Backend"]
+ DecoratorsParser --> Logger["Logger"]
+ EventsParser --> EventsCore["Events Framework"]
+```
+
+### Key Responsibilities
+
+- Load configuration from local files or remote sources.
+- Merge layered configuration files.
+- Parse specific configuration sections.
+- Update flags and runtime settings.
+- Dynamically create SQL views.
+- Register file paths and event subscriptions.
+- Enrich logs with runtime decorations.
+
+---
+
+# ConfigPlugin Implementations
+
+Config plugins generate configuration data for the core engine.
+
+## FilesystemConfigPlugin
+
+**Component:** `osquery.plugins.config.filesystem_config.FilesystemConfigPlugin`
+
+The Filesystem Config Plugin loads configuration from disk.
+
+### Responsibilities
+
+- Read the primary config file defined by the `config_path` flag.
+- Load layered configuration files from a `.d` directory.
+- Support multi-pack generation using glob patterns.
+- Validate file existence before parsing.
+
+### Layered Config Resolution
+
+```mermaid
+flowchart TD
+ Start["Start genConfig()"] --> CheckFile["Check config_path exists"]
+ CheckFile -->|"valid"| LoadDir["Resolve config_path.d/*.conf"]
+ LoadDir --> SortFiles["Sort files"]
+ SortFiles --> Merge["Append main config"]
+ Merge --> Output["Return map of source to JSON"]
+ CheckFile -->|"invalid"| Fail["Return failure Status"]
+```
+
+### Multi-Pack Support
+
+If a pack name is `*`, the plugin:
+
+- Resolves a file pattern.
+- Reads each JSON file.
+- Builds a synthetic JSON object keyed by filename.
+- Emits a merged pack blob.
+
+This allows external pack directories to behave like embedded pack definitions.
+
+---
+
+## UpdateConfigPlugin
+
+**Component:** `osquery.plugins.config.update.UpdateConfigPlugin`
+
+The Update Config Plugin is a special routing plugin that enables:
+
+- Extension-driven configuration updates.
+- Asynchronous config refresh propagation.
+
+It does not generate configuration directly. Instead, it provides a mechanism for extensions to call `Config::update`, allowing core osquery to refresh configuration state.
+
+This enables safe plugin-to-core state mutation without violating registry boundaries.
+
+---
+
+# ConfigParserPlugin Implementations
+
+Parser plugins operate on specific top-level configuration keys and update internal runtime structures.
+
+---
+
+## DecoratorsConfigParserPlugin
+
+**Component:** `osquery.plugins.config.parsers.decorators.DecoratorsConfigParserPlugin`
+
+Decorators allow SQL queries to append additional key-value pairs to:
+
+- Query results
+- Snapshot logs
+- Status logs
+
+### Supported Decoration Points
+
+- `load` β executed when config is loaded.
+- `always` β executed before every query.
+- `interval` β executed on configured intervals.
+
+### Decoration Execution Flow
+
+```mermaid
+flowchart TD
+ ConfigLoad["Config Updated"] --> ParseDecorators["Parse decorators JSON"]
+ ParseDecorators --> StoreQueries["Store queries by point"]
+ StoreQueries --> RunLoad["Run load decorators"]
+
+ Scheduler["Query Scheduler"] --> RunAlways["Run always decorators"]
+ Scheduler --> RunInterval["Run interval decorators"]
+
+ RunLoad --> SQLExec["Execute SQL"]
+ RunAlways --> SQLExec
+ RunInterval --> SQLExec
+
+ SQLExec --> DecorationStore["Store first row columns"]
+ DecorationStore --> Logger["Attach to logs"]
+```
+
+### Key Design Considerations
+
+- Only the first row of a decorator query is used.
+- Duplicate column names cause undefined behavior.
+- Interval decorators must be multiples of 60 seconds.
+- Thread-safe access is enforced via mutexes.
+- Can be disabled using the `disable_decorators` flag.
+
+Decorations directly enrich data consumed by the [Logging and Query Metadata](../logging-and-query-metadata/logging-and-query-metadata.md) module.
+
+---
+
+## EventsConfigParserPlugin
+
+**Component:** `osquery.plugins.config.parsers.events_parser.EventsConfigParserPlugin`
+
+Parses the `events` configuration key and publishes structured event configuration into the shared config state.
+
+### Responsibilities
+
+- Copy `events` JSON subtree into parser data.
+- Expose structured event configuration to the [Events Core and Subscriptions](../events-core-and-subscriptions/events-core-and-subscriptions.md) module.
+
+This parser performs minimal transformation and acts primarily as a structured pass-through.
+
+---
+
+## FilePathsConfigParserPlugin
+
+**Component:** `osquery.plugins.config.parsers.file_paths.FilePathsConfigParserPlugin`
+
+Manages file-based monitoring configuration.
+
+### Supported Keys
+
+- `file_paths`
+- `file_paths_query`
+- `file_accesses`
+- `exclude_paths`
+
+### Processing Pipeline
+
+```mermaid
+flowchart TD
+ ConfigUpdate["Config Update"] --> RemoveOld["Remove existing files for source"]
+ RemoveOld --> ParseFilePaths["Parse file_paths"]
+ RemoveOld --> ParseQuery["Parse file_paths_query"]
+ RemoveOld --> ParseAccess["Parse file_accesses"]
+ RemoveOld --> ParseExclude["Parse exclude_paths"]
+
+ ParseFilePaths --> Register["Config::addFile()"]
+ ParseQuery --> SQLExec["Execute SQL query"]
+ SQLExec --> Register
+
+ ParseAccess --> AccessMap["Build access map"]
+ ParseExclude --> MergeExclude["Merge exclude paths"]
+```
+
+### Notable Behaviors
+
+- Glob wildcards are normalized before registration.
+- SQL-driven path discovery must return a `path` column.
+- Exclusions are merged across sources.
+- File registrations are source-aware and can be removed on update.
+
+This parser integrates closely with filesystem monitoring and the event subsystem.
+
+---
+
+## OptionsConfigParserPlugin
+
+**Component:** `osquery.plugins.config.parsers.options.OptionsConfigParserPlugin`
+
+Handles runtime flag configuration via the `options` key.
+
+### Responsibilities
+
+- Merge configuration options across sources.
+- Validate flag existence.
+- Ignore CLI-only flags.
+- Update flag values dynamically.
+- Trigger verbosity reconfiguration if needed.
+
+### Flag Update Flow
+
+```mermaid
+flowchart TD
+ ParseOptions["Parse options JSON"] --> Validate["Validate flag name"]
+ Validate -->|"invalid"| Warn["Log warning"]
+ Validate -->|"valid"| UpdateFlag["Flag::updateValue()"]
+ UpdateFlag --> CheckVerbose["Is verbosity option?"]
+ CheckVerbose -->|"yes"| Reconfigure["setVerboseLevel()"]
+```
+
+### Important Constraints
+
+- Unknown flags are rejected.
+- CLI-only flags cannot be set via config.
+- Custom flags must begin with `custom_`.
+
+This parser directly affects behavior across the entire osquery runtime.
+
+---
+
+## ViewsConfigParserPlugin
+
+**Component:** `osquery.plugins.config.parsers.views.ViewsConfigParserPlugin`
+
+Creates and manages dynamic SQL views defined in configuration.
+
+### Responsibilities
+
+- Parse `views` dictionary.
+- Create or update SQL views.
+- Persist view definitions in the database.
+- Drop views removed from configuration.
+
+### View Lifecycle
+
+```mermaid
+flowchart TD
+ ParseViews["Parse views JSON"] --> LoadExisting["Scan database keys"]
+ LoadExisting --> Compare["Compare old vs new"]
+ Compare -->|"changed or new"| DropOld["DROP VIEW"]
+ DropOld --> CreateNew["CREATE VIEW AS query"]
+ CreateNew --> Persist["Store in database"]
+ Compare -->|"removed"| Remove["Delete database entry"]
+```
+
+### Integration Points
+
+- Executes SQL using the [SQL Engine and Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md).
+- Persists metadata in the [Database Backend](../database-backend/database-backend.md).
+
+The plugin ensures idempotency by skipping recreation when definitions have not changed, except during first initialization.
+
+---
+
+# End-to-End Configuration Flow
+
+```mermaid
+flowchart TD
+ Source["Filesystem or Remote Source"] --> ConfigPlugin["ConfigPlugin"]
+ ConfigPlugin --> ConfigCore["Config Core"]
+ ConfigCore --> ParserPlugins["ConfigParserPlugins"]
+ ParserPlugins --> RuntimeState["Runtime State"]
+
+ RuntimeState --> Scheduler["Query Scheduler"]
+ RuntimeState --> Logger
+ RuntimeState --> Events
+ RuntimeState --> SQL
+```
+
+### Lifecycle Summary
+
+1. A Config Plugin generates raw configuration blobs.
+2. The Config Core merges and normalizes them.
+3. Each Config Parser Plugin processes relevant keys.
+4. Runtime state is updated atomically.
+5. Dependent subsystems react (scheduler, logger, SQL engine, events).
+
+---
+
+# Design Characteristics
+
+- **Registry-based extensibility** β Plugins register themselves dynamically.
+- **Source-aware merging** β Each config source is tracked independently.
+- **Thread-safe decoration handling** β Mutex-protected shared state.
+- **Idempotent updates** β Avoid unnecessary re-creation of views or flags.
+- **Loose coupling** β Parsers modify only their scoped domain.
+
+---
+
+# Relationship to Other Modules
+
+| Concern | Module |
+|----------|--------|
+| Config refresh scheduling | [Configuration and Packs](../configuration-and-packs/configuration-and-packs.md) |
+| Query execution | [SQL Engine and Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md) |
+| View persistence | [Database Backend](../database-backend/database-backend.md) |
+| Log enrichment | [Logging and Query Metadata](../logging-and-query-metadata/logging-and-query-metadata.md) |
+| Event subscription behavior | [Events Core and Subscriptions](../events-core-and-subscriptions/events-core-and-subscriptions.md) |
+
+---
+
+# Conclusion
+
+The **Config Plugins** module forms the dynamic configuration backbone of osquery. It transforms static or remote JSON configuration into structured runtime behavior, enabling:
+
+- Flexible deployment models
+- Dynamic reconfiguration
+- Cross-module feature activation
+- Extension-driven updates
+
+By cleanly separating configuration sourcing from configuration parsing, this module ensures extensibility, modularity, and safe runtime evolution of system behavior.
\ No newline at end of file
diff --git a/docs/reference/architecture/configuration-and-packs/configuration-and-packs.md b/docs/reference/architecture/configuration-and-packs/configuration-and-packs.md
index f9ca515ae14..6fe3415ebb0 100644
--- a/docs/reference/architecture/configuration-and-packs/configuration-and-packs.md
+++ b/docs/reference/architecture/configuration-and-packs/configuration-and-packs.md
@@ -1,383 +1,365 @@
# Configuration And Packs
-The **Configuration And Packs** module is responsible for loading, validating, parsing, distributing, and refreshing osquery configuration data. It transforms raw configuration sources (files, extensions, or remote plugins) into:
+## Overview
-- Scheduled queries and packs
-- File monitoring rules
-- Event subscriptions
-- Logger and runtime options
-- SQL views
-- Decorations and metadata
+The **Configuration And Packs** module is responsible for:
-This module acts as the *control plane* for osquery runtime behavior. It connects configuration sources with the scheduler, SQL engine, eventing framework, logging pipeline, and database layer.
+- Loading configuration data from pluggable configuration providers
+- Parsing and validating JSON configuration documents
+- Building and maintaining the scheduled query packs
+- Managing discovery queries, sharding, and platform/version constraints
+- Tracking query performance and denylisting unstable queries
+- Coordinating reconfiguration across the system when configuration changes
----
+This module acts as the **control plane** for scheduled execution. It translates raw configuration into executable query schedules and propagates changes to other subsystems such as:
+
+- [SQL Engine And Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md)
+- [Logging And Query Metadata](../logging-and-query-metadata/logging-and-query-metadata.md)
+- [Database Backend](../database-backend/database-backend.md)
+- [Events Core And Subscriptions](../events-core-and-subscriptions/events-core-and-subscriptions.md)
+- [Extensions Framework](../extensions-framework/extensions-framework.md)
-## Architecture Overview
+---
-At a high level, the module consists of:
+## Architectural Overview
-- A **Config registry** for loading configuration sources
-- A **ConfigRefreshRunner** background service
-- A **Schedule** abstraction built from Packs
-- Multiple **ConfigParserPlugin** implementations
-- Backup, hashing, and validation logic
+At a high level, configuration flows through the system as follows:
```mermaid
flowchart TD
- ConfigPlugin["Config Plugin Registry"] --> ConfigCore["Config Singleton"]
- ConfigCore --> RefreshRunner["ConfigRefreshRunner"]
- ConfigCore --> Schedule["Schedule"]
- Schedule --> Pack["Pack"]
- ConfigCore --> Parsers["ConfigParserPlugins"]
- Parsers --> OptionsParser["Options Parser"]
- Parsers --> FilePathsParser["File Paths Parser"]
- Parsers --> DecoratorsParser["Decorators Parser"]
- Parsers --> EventsParser["Events Parser"]
- Parsers --> ViewsParser["Views Parser"]
- ConfigCore --> Database[("Persistent Database")]
- Schedule --> Logging["Logging And Query Observability"]
- Schedule --> SQLEngine["SQL Engine And Virtual Tables"]
- Parsers --> EventFramework["Eventing Framework"]
+ ConfigPlugin["Config Plugin Registry"] -->|"genConfig"| ConfigCore["Config Singleton"]
+ ConfigCore -->|"updateSource"| JSONValidation["JSON Validation"]
+ JSONValidation --> Packs["Pack Objects"]
+ Packs --> Schedule["Schedule Manager"]
+ Schedule --> SQL["SQL Engine"]
+ Schedule --> Logger["Logger Plugins"]
+ ConfigCore --> Database["Database Backend"]
+ ConfigCore --> EventFactory["Event Factory"]
+ ConfigCore --> Registry["Plugin Registry"]
```
+### Key Responsibilities
+
+| Layer | Responsibility |
+|--------|----------------|
+| Config Plugin | Supplies raw configuration (filesystem, TLS, etc.) |
+| Config | Validates, parses, hashes, and updates runtime state |
+| Pack | Represents a logical bundle of scheduled queries |
+| Schedule | Filters active packs and manages denylisting |
+| Database | Persists performance stats, hashes, backups |
+| Registry | Reconfigures plugins after config updates |
+
---
-## Core Responsibilities
+## Core Components
-### 1. Configuration Loading
+### 1. ConfigRefreshRunner
-The module defines a `config` registry that supports pluggable configuration sources:
+**Component:** `osquery.osquery.config.config.ConfigRefreshRunner`
-- `FilesystemConfigPlugin` (default)
-- `UpdateConfigPlugin` (internal chaining for extensions)
+This internal runnable is responsible for periodic configuration refresh.
-Each plugin implements:
+#### Responsibilities
-- `genConfig()` β produce configuration map
-- `genPack()` β resolve pack references
-- `update()` β apply configuration updates
+- Sleeps for `config_refresh` interval
+- Calls `Config::refresh()`
+- Accelerates retry interval when refresh fails
+- Stops when shutdown is requested
-The active plugin is selected via the `config_plugin` flag.
+#### Refresh Lifecycle
----
+```mermaid
+flowchart TD
+ Start["Thread Start"] --> Pause["Sleep refresh_sec"]
+ Pause --> Check["Interrupted?"]
+ Check -->|"Yes"| End["Stop"]
+ Check -->|"No"| Refresh["Config.refresh()"]
+ Refresh --> Pause
+```
-### 2. Config Singleton
+Refresh interval behavior:
-The `Config` class is a process-wide singleton that:
+- Normal interval: `config_refresh`
+- Failure interval: `config_accelerated_refresh`
+- Optional backup restore on first failure
-- Loads configuration
-- Maintains the active Schedule
-- Applies parser plugins
-- Tracks source hashes
-- Backs up and restores configuration
-- Coordinates plugin reconfiguration
+---
-Key behaviors:
+### 2. Config
-- JSON validation (max depth and size constraints)
-- Comment stripping
-- Hash-based change detection
-- Safe concurrent access using mutexes
-- Performance tracking per scheduled query
+The `Config` class is a **singleton control center** for configuration state.
----
+#### Primary Responsibilities
-### 3. Refresh Lifecycle
+- Call active config plugin (`genConfig`)
+- Validate JSON structure and depth
+- Hash sources to detect changes
+- Build and update packs
+- Apply config parser plugins
+- Purge stale query results
+- Trigger registry reconfiguration
+- Manage performance stats and denylisting
-The `ConfigRefreshRunner` runs in the background when `config_refresh` is enabled.
+#### Configuration Update Flow
```mermaid
flowchart TD
- Start["ConfigRefreshRunner Start"] --> Wait["Sleep refresh_sec"]
- Wait --> Check["Interrupted?"]
- Check -->|No| Refresh["Config.refresh()"]
- Refresh --> Wait
- Check -->|Yes| End["End"]
+ Gen["Registry.call genConfig"] --> Update["Config.update()"]
+ Update --> Purge["Purge stale queries"]
+ Purge --> UpdateSource["updateSource(source)"]
+ UpdateSource --> Validate["Validate JSON"]
+ Validate --> Extract["Extract schedule and packs"]
+ Extract --> ApplyParsers["Apply config parsers"]
+ ApplyParsers --> Reconfigure["Reconfigure registries"]
+ Reconfigure --> Done["Config Valid"]
```
-Features:
-
-- Normal refresh interval
-- Accelerated retry interval on failure
-- Optional backup restoration on first failure
-- Dynamic reconfiguration of registries and loggers
-
---
## Packs and Scheduling
-The Schedule is composed of `Pack` objects.
+### 3. Pack
-### Pack
+**Component:** `osquery.osquery.config.packs.Pack`
-A **Pack** represents a group of scheduled queries plus optional discovery logic.
+A Pack represents a logical bundle of scheduled queries.
-Capabilities:
+Each pack may contain:
+- Discovery queries
+- Scheduled queries
- Platform constraints
- Version constraints
- Shard percentage
-- Discovery queries
-- ScheduledQuery collection
-- Execution eligibility (`shouldPackExecute()`)
-### Schedule
+#### Pack Execution Logic
-The Schedule:
+A pack is considered active when:
-- Maintains active packs
-- Filters packs via discovery checks
-- Tracks denylisted queries
-- Restores failed queries on restart
-- Provides query iteration to the scheduler
+1. Platform check passes
+2. Version check passes
+3. Shard requirement matches
+4. Discovery queries return expected results
```mermaid
flowchart TD
- ConfigUpdate["Config Update"] --> BuildPacks["Create Pack Objects"]
- BuildPacks --> DiscoveryCheck["Discovery Queries"]
- DiscoveryCheck --> ActivePack["Active Pack"]
- ActivePack --> Scheduler["ScheduledQuery Execution"]
- Scheduler --> Performance["Query Performance Recording"]
- Scheduler --> Denylist["Denylist On Failure"]
+ Platform["Check Platform"] --> Version["Check Version"]
+ Version --> Shard["Check Shard"]
+ Shard --> Discovery["Run Discovery Queries"]
+ Discovery --> Active["Pack Active"]
```
-### Denylist Logic
-
-If a scheduled query:
-
-- Causes watchdog termination
-- Was executing during shutdown
-
-It is denylisted temporarily and persisted in the database.
-
-Expiration logic considers:
-
-- Time-based expiry
-- Event-based exemptions
-- Explicit `denylist=false` option
+Pack state is cached to avoid repeatedly executing discovery queries unnecessarily.
---
-## Config Parser Plugins
+### 4. Schedule
-The module defines a `config_parser` registry. Each parser consumes specific top-level configuration keys.
+The `Schedule` class maintains all active packs.
-Parsers are applied in this order:
+It:
-1. Options parser (always first)
-2. Remaining parsers in registry order
+- Stores pack objects
+- Filters packs using `shouldPackExecute()`
+- Tracks failed queries
+- Maintains denylist with expiration
+- Restores denylist from persistent storage
-### FilesystemConfigPlugin
+#### Denylist Behavior
-Loads configuration from:
+When a scheduled query crashes or exceeds watchdog limits:
-- Primary JSON file
-- Optional `.d` directory fragments
-- Multi-pack glob patterns
+- It is written to the database (`failed_queries`)
+- Added to in-memory denylist
+- Skipped during scheduling
+- Automatically expires after a timeout
-Produces a map of `source β JSON content`.
+```mermaid
+flowchart TD
+ Failure["Query Failure"] --> Persist["Persist to Database"]
+ Persist --> Denylist["Add to Denylist"]
+ Denylist --> Skip["Skip During Scheduling"]
+ Skip --> Expire["Expiration Check"]
+ Expire -->|"Expired"| Reactivate["Allow Execution"]
+```
---
-### OptionsConfigParserPlugin
+## Pack Statistics
-Handles the `options` key.
+### 5. PackStats
-- Updates runtime flags
-- Prevents modification of CLI-only flags
-- Reconfigures logger verbosity dynamically
-- Supports `custom_` prefixed flags
+**Component:** `osquery.osquery.config.packs.PackStats`
----
+Tracks discovery query effectiveness:
-### FilePathsConfigParserPlugin
+| Field | Meaning |
+|-------|----------|
+| total | Total discovery executions |
+| hits | Successful discovery matches |
+| misses | Discovery failures |
-Handles:
+These metrics help determine whether packs are frequently inactive due to discovery logic.
-- `file_paths`
-- `file_paths_query`
-- `file_accesses`
-- `exclude_paths`
+---
-Responsibilities:
+## Configuration Parsers
-- Adds file monitoring rules to Config
-- Executes SQL-based path discovery
-- Normalizes wildcard globs
-- Maintains access category mappings
+The module defines a **config_parser registry**.
-This integrates directly with the **Filesystem And Path Utilities** and **Eventing Framework And Subscriptions** modules.
+Parser plugins:
----
+- Receive JSON fragments by key
+- Update subsystem state
+- Do not expose call actions
+- Operate through structured property trees
-### DecoratorsConfigParserPlugin
+Execution order:
-Handles the `decorators` key.
+1. `options` parser (always first)
+2. Remaining parsers
-Decorators:
+This ensures flags and options are configured before dependent parsers execute.
-- Execute SQL queries
-- Extract first-row column values
-- Attach results to logs
+---
+
+## Backup and Restore
-Supported execution points:
+If `config_enable_backup` is enabled:
-- `load`
-- `always`
-- `interval`
+- Each config source is persisted with prefix `config_persistence.`
+- On first refresh failure, backup is restored
+- Old keys are pruned on update
```mermaid
flowchart TD
- ConfigLoad["Config Load"] --> RunLoad["Run Load Decorators"]
- QueryExec["Query Execution"] --> RunAlways["Run Always Decorators"]
- IntervalTick["Interval Timer"] --> RunInterval["Run Interval Decorators"]
- RunLoad --> Decorations[("Decoration Store")]
- RunAlways --> Decorations
- RunInterval --> Decorations
- Decorations --> Logger["Status And Query Logs"]
+ Update["Successful Update"] --> Backup["Backup Config Sources"]
+ Failure["Refresh Failure"] --> Restore["Restore From Database"]
+ Restore --> Update
```
-Thread safety is enforced with dedicated mutexes.
-
---
-### EventsConfigParserPlugin
+## Query Performance Tracking
-Consumes the `events` key and exposes configuration to event publishers and subscribers.
-
-Acts as a bridge to the **Eventing Framework And Subscriptions** module.
-
----
+The module integrates tightly with [Logging And Query Metadata](../logging-and-query-metadata/logging-and-query-metadata.md).
-### ViewsConfigParserPlugin
+### Recorded Metrics
-Handles the `views` key.
+- Wall time
+- User time
+- System time
+- Memory usage delta
+- Output size
+- Execution count
+- Last executed timestamp
-- Creates SQL views
-- Drops outdated views
-- Persists view definitions
-- Ensures idempotent updates
+Performance is stored in the database under `kQueryPerformance`.
-This integrates with the **SQL Engine And Virtual Tables** module.
+When queries are modified or removed, performance data is cleared to avoid stale metrics.
---
-## Backup and Persistence
+## Purge and Expiration
-If `config_enable_backup` is enabled:
-
-- Config sources are stored in the database
-- Failed refresh attempts restore backup
-- Backup keys are namespaced with `config_persistence.`
+During updates, the module:
-The module also persists:
+- Scans persisted query result sets
+- Removes entries for queries no longer in schedule
+- Expires results older than one week
-- Query performance statistics
-- Executing query markers
-- Denylist entries
-- Query result timestamps
-
-Database interactions use the **Database And Storage Plugins** module.
+This prevents unbounded database growth and stale result accumulation.
---
## Hashing and Change Detection
-Each configuration source is hashed (SHA1):
+Each configuration source is hashed using SHA1.
-- Prevents unnecessary reconfiguration
-- Enables selective updates
-- Supports global config hash generation
+If the hash does not change:
-If a source hash does not change:
+- The source is skipped
+- Reconfiguration is avoided
-- Packs are not rebuilt
-- Parsers are not re-applied
+A global configuration hash can be generated by combining source hashes.
+
+```mermaid
+flowchart LR
+ SourceA["Source A Hash"] --> Combine["Combine Hashes"]
+ SourceB["Source B Hash"] --> Combine
+ Combine --> Global["Global Config Hash"]
+```
---
-## Interaction With Other Modules
+## Thread Safety
-### Logging And Query Observability
+The module uses multiple mutexes:
-- Query performance stats recorded
-- Decorations attached to logs
-- Denylist logging
+- `config_hash_mutex_`
+- `config_refresh_mutex_`
+- `config_backup_mutex_`
+- `config_schedule_mutex_`
+- `config_files_mutex_`
+- `config_performance_mutex_`
-### SQL Engine And Virtual Tables
+This ensures:
-- Discovery queries
-- Scheduled queries
-- View creation
+- Safe concurrent refresh
+- Safe schedule iteration
+- Consistent performance updates
+- Atomic configuration transitions
-### Eventing Framework And Subscriptions
+---
-- Event configuration via `events`
-- File path monitoring integration
+## Integration with Other Modules
-### Database And Storage Plugins
+### Core Runtime And Lifecycle
-- Config backup
-- Query stats
-- Denylist persistence
-- Result expiration
+- Refresh thread runs through dispatcher
+- Shutdown interrupts refresh loop
-### Extensions And IPC
+### Database Backend
-- External extensions can call `Config::update()`
-- UpdateConfigPlugin enables update chaining
-- External registries propagate updates back to core
+Used for:
----
+- Denylist persistence
+- Performance metrics
+- Backup storage
+- Query timestamp tracking
-## Configuration Processing Flow
+### Extensions Framework
-```mermaid
-flowchart TD
- Source["Config Source"] --> GenConfig["genConfig()"]
- GenConfig --> Update["Config.update()"]
- Update --> Purge["Purge Stale State"]
- Purge --> UpdateSource["updateSource()"]
- UpdateSource --> ParseJSON["Validate And Parse JSON"]
- ParseJSON --> BuildSchedule["Create Packs And Schedule"]
- BuildSchedule --> ApplyParsers["Apply ConfigParserPlugins"]
- ApplyParsers --> Reconfigure["Registry.configure()"]
- Reconfigure --> EventNotify["EventFactory.configUpdate()"]
- EventNotify --> Ready["Runtime Updated"]
-```
+- External processes may call `update`
+- Updates are forwarded to core
+- Extension configs propagate to main runtime
----
+### Events Core And Subscriptions
-## Concurrency and Safety
+After configuration changes:
-The module uses:
+- Event publishers and subscribers are reconfigured
+- `EventFactory::configUpdate()` is triggered
-- Recursive mutexes for schedule and files
-- Dedicated mutexes for:
- - Hash map
- - Backup store
- - Performance stats
- - Decorations
+---
-Design goals:
+## Summary
-- Safe asynchronous refresh
-- Deterministic schedule rebuilds
-- Minimal runtime disruption
-- Atomic config transitions
+The **Configuration And Packs** module is the orchestration layer that:
----
+- Converts configuration into executable schedules
+- Controls pack activation and filtering
+- Protects runtime stability through denylisting
+- Maintains deterministic scheduling behavior
+- Coordinates dynamic reconfiguration across subsystems
-## Summary
+It is central to runtime adaptability, reliability, and consistency of scheduled query execution.
-The **Configuration And Packs** module is the orchestration layer of osquery runtime behavior. It:
+Without this module, the system would lack:
-- Loads configuration from pluggable sources
-- Builds and manages query packs
-- Applies runtime options
-- Coordinates parser plugins
-- Manages refresh and backup logic
-- Integrates deeply with scheduler, SQL engine, event system, logging, and database layers
+- Dynamic configuration refresh
+- Safe scheduling guarantees
+- Distributed pack management
+- Query lifecycle observability
-Without this module, osquery would have no dynamic runtime control plane. It is the central authority that transforms static configuration data into active system behavior.
+It forms the backbone of runtime query orchestration within the platform.
\ No newline at end of file
diff --git a/docs/reference/architecture/core-init-and-runtime/core-init-and-runtime.md b/docs/reference/architecture/core-init-and-runtime/core-init-and-runtime.md
deleted file mode 100644
index 03460755d71..00000000000
--- a/docs/reference/architecture/core-init-and-runtime/core-init-and-runtime.md
+++ /dev/null
@@ -1,428 +0,0 @@
-# Core Init And Runtime
-
-The **Core Init And Runtime** module is the foundational execution layer of osquery. It is responsible for:
-
-- Process initialization and bootstrap
-- Command-line flag management
-- Worker / watcher lifecycle orchestration
-- Graceful and forced shutdown handling
-- Platform and identity utilities (UUID, host identity, privilege control)
-- Virtual table execution context and constraint handling
-- Watchdog-based resource governance
-
-This module defines the runtime contract that all higher-level subsystems rely on, including:
-
-- [Configuration And Packs](../configuration-and-packs/configuration-and-packs.md)
-- [Logging And Query Observability](../logging-and-query-observability/logging-and-query-observability.md)
-- [Database And Storage Plugins](../database-and-storage-plugins/database-and-storage-plugins.md)
-- [SQL Engine And Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md)
-- [Eventing Framework And Subscriptions](../eventing-framework-and-subscriptions/eventing-framework-and-subscriptions.md)
-- [Extensions And IPC](../extensions-and-ipc/extensions-and-ipc.md)
-
----
-
-## 1. Architectural Overview
-
-At runtime, osquery can operate in multiple modes:
-
-- **Daemon** (`osqueryd`)
-- **Shell** (`osqueryi`)
-- **Watcher (watchdog)**
-- **Worker** (child process of watcher)
-- **Extension process**
-
-The Core Init And Runtime module orchestrates how these modes are selected, started, monitored, and shut down.
-
-### High-Level Runtime Architecture
-
-```mermaid
-flowchart TD
- Main["Main Entry Point"] --> Initializer["Initializer"]
-
- Initializer --> Flags["Flag System"]
- Initializer --> Registry["Registry And Plugins"]
- Initializer --> Database["Database Initialization"]
- Initializer --> ExtensionManager["Extension Manager"]
- Initializer --> Events["Event Factory"]
- Initializer --> Watchdog["Watcher / Worker Model"]
-
- Watchdog --> Worker["Worker Process"]
- Watchdog --> Extensions["Extension Processes"]
-
- Worker --> Tables["Virtual Tables"]
- Worker --> Scheduler["Query Scheduler"]
- Worker --> Logger["Logger Plugins"]
-```
-
-The **Initializer** class is the central orchestrator of this lifecycle.
-
----
-
-## 2. Initialization Lifecycle
-
-The `Initializer` class (defined in `system.h` and implemented in `init.cpp`) governs startup behavior.
-
-### Core Responsibilities
-
-- Parse CLI flags and flagfiles
-- Determine tool type (daemon, shell, extension)
-- Configure runtime defaults
-- Initialize registries and plugins
-- Start extension manager
-- Load configuration
-- Attach event publishers
-- Activate logging and distributed plugins
-- Launch watcher/worker model if enabled
-
-### Startup Sequence
-
-```mermaid
-sequenceDiagram
- participant Main
- participant Initializer
- participant Registry
- participant Config
- participant Extensions
- participant Events
-
- Main->>Initializer: Construct(argc, argv)
- Initializer->>Initializer: Parse flags
- Initializer->>Registry: registryAndPluginInit()
- Initializer->>Extensions: startExtensionManager()
- Initializer->>Config: load()
- Initializer->>Events: attachEvents()
- Initializer->>Initializer: start()
-```
-
-The `start()` method finalizes runtime activation after construction.
-
----
-
-## 3. Flag System
-
-Core Components:
-
-- `FlagDetail`
-- `FlagInfo`
-- `Flag`
-
-The flag system wraps **Google GFlags** to provide:
-
-- Structured metadata (shell-only, CLI-only, hidden, extension-only)
-- Default value tracking
-- Runtime updates
-- Custom flags from configuration
-
-### Flag Architecture
-
-```mermaid
-flowchart LR
- Macro["FLAG / CLI_FLAG Macros"] --> FlagCreate["Flag::create()"]
- FlagCreate --> FlagRegistry["Internal Flag Map"]
-
- CLI["Command Line"] --> Parse["ParseCommandLineFlags"]
- Config["Config Options"] --> Update["Flag::updateValue()"]
-
- FlagRegistry --> Runtime["Runtime Access"]
-```
-
-Important behaviors:
-
-- Flags can be set via CLI, flagfile, or config (unless CLI-only)
-- `Flag::isDefault()` detects overridden values
-- Aliases support backwards compatibility
-
-Flags influence:
-
-- Database activation
-- Watchdog enablement
-- Logging and distributed plugins
-- OpenFrame mode
-
----
-
-## 4. Worker and Watcher Model
-
-Core Components:
-
-- `LimitDefinition`
-- `PerformanceChange`
-
-The watcher/worker architecture isolates execution for reliability and resource control.
-
-### Roles
-
-| Role | Responsibility |
-|------|----------------|
-| Watcher | Monitors worker and extensions |
-| Worker | Executes queries and plugins |
-| Extension | External plugin process |
-
-### Watchdog Control Flow
-
-```mermaid
-flowchart TD
- Watcher["Watcher Process"] --> Spawn["Spawn Worker"]
- Spawn --> Monitor["Monitor CPU And Memory"]
- Monitor --> Check{{"Limit Exceeded?"}}
- Check -->|"No"| Continue["Continue Monitoring"]
- Check -->|"Yes"| Kill["Stop Worker"]
- Kill --> Respawn["Respawn Worker"]
-```
-
-### Resource Limits
-
-`LimitDefinition` defines profiles:
-
-- Normal
-- Restrictive
-- Disabled
-
-Enforced metrics:
-
-- Memory footprint (MB)
-- CPU utilization percentage
-- Sustained latency duration
-- Respawn frequency
-
-`PerformanceChange` calculates CPU window utilization based on interval and CPU count.
-
-If limits are exceeded:
-
-- Worker is gracefully terminated
-- Forced kill occurs if needed
-- Restart logic applies exponential backoff
-
----
-
-## 5. Shutdown Coordination
-
-Core Component:
-
-- `ShutdownData`
-
-Shutdown is centralized and thread-safe.
-
-### Shutdown Model
-
-```mermaid
-flowchart TD
- AnyThread["Any Thread"] --> Request["requestShutdown()"]
- Request --> Signal["Condition Variable"]
- Signal --> MainThread["Main Thread"]
- MainThread --> StopServices["Dispatcher::stopServices()"]
- StopServices --> Join["Join Services"]
- Join --> StopEvents["EventFactory::end()"]
- StopEvents --> CloseDB["shutdownDatabase()"]
- CloseDB --> Exit["Return Exit Code"]
-```
-
-Key properties:
-
-- Shutdown can only be requested once
-- Exit code is stored atomically
-- `AlarmRunnable` enforces maximum shutdown time
-- `shutdownNow()` performs immediate `_Exit()`
-
-This guarantees deterministic teardown even during deadlocks.
-
----
-
-## 6. Platform and System Utilities
-
-Core Components:
-
-- `PrivateData`
-- `stat`
-- `tm`
-
-### Host Identity
-
-The module manages multiple UUID strategies:
-
-- Hardware UUID
-- Instance UUID (persistent)
-- Ephemeral UUID
-- Specified UUID
-- Hostname fallback
-
-Flow:
-
-```mermaid
-flowchart LR
- Flag["host_identifier Flag"] --> Mode{{"Mode"}}
- Mode -->|"uuid"| Hardware["Hardware UUID"]
- Mode -->|"instance"| Instance["Instance UUID"]
- Mode -->|"ephemeral"| Ephemeral["Random UUID"]
- Mode -->|"specified"| Specified["Configured Identifier"]
- Mode -->|"default"| Hostname["System Hostname"]
-```
-
-Persistent identifiers are stored via the database layer.
-
-### Privilege Dropping (POSIX)
-
-- Temporarily reduce effective UID/GID
-- Restore original groups on destruction
-- Used when interacting with filesystem-backed tables
-
-### Thread Naming
-
-Cross-platform thread naming for observability and debugging.
-
----
-
-## 7. Virtual Table Execution Context
-
-Core Components:
-
-- `Constraint`
-- `ConstraintList`
-- `QueryContext`
-- `VirtualTableContent`
-
-This subsystem forms the bridge between:
-
-- SQLite virtual table engine
-- osquery table plugins
-
-### Constraint Model
-
-```mermaid
-flowchart TD
- SQL["SQL Query"] --> SQLite["SQLite Virtual Table API"]
- SQLite --> QueryContext["QueryContext"]
- QueryContext --> ConstraintMap["ConstraintMap"]
- ConstraintMap --> ConstraintList["ConstraintList"]
- ConstraintList --> TablePlugin["TablePlugin::generate()"]
-```
-
-`ConstraintList` supports:
-
-- Operator-aware filtering
-- Affinity-aware matching (TEXT, INTEGER, BIGINT)
-- Efficient pre-filter evaluation
-
-`QueryContext` provides:
-
-- Column usage tracking
-- Constraint expansion
-- Cache control flags
-
-### VirtualTableContent
-
-Stores:
-
-- Column definitions
-- Attributes (CACHEABLE, EVENT_BASED, etc.)
-- Aliases
-- Query-scoped caches
-
-This metadata allows high-performance virtual table execution without repeated registry lookups.
-
----
-
-## 8. Table Plugin Integration
-
-Although fully described in [SQL Engine And Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md), Core Init And Runtime provides:
-
-- Context serialization
-- Cache freshness checks
-- Generator-based row streaming
-- Extension table attachment
-
-Caching model:
-
-- Interval-based freshness
-- Disabled when constraints are complex
-- Serialized into backing database
-
----
-
-## 9. Signal Handling
-
-Signals handled:
-
-- `SIGTERM`
-- `SIGINT`
-- `SIGUSR1`
-
-Behavior:
-
-- `SIGUSR1` β mark resource limit hit
-- `SIGTERM` / `SIGINT` β request graceful shutdown
-- Alarm timeout enforces upper bound on shutdown time
-
----
-
-## 10. OpenFrame Mode Integration
-
-Additional flags:
-
-- `openframe_mode`
-- `openframe_secret`
-- `openframe_token_path`
-
-When enabled:
-
-- Initializes encryption service
-- Extracts token
-- Starts token refresher
-- Updates authorization manager
-
-This integrates osquery runtime with OpenFrame-managed authentication.
-
----
-
-## 11. How This Module Fits the System
-
-The Core Init And Runtime module:
-
-- Bootstraps **all subsystems**
-- Owns lifecycle and teardown guarantees
-- Provides runtime isolation (watchdog model)
-- Supplies identity and environment context
-- Enables safe virtual table execution
-- Enforces resource governance
-
-Every other module depends on it either directly or indirectly.
-
-### Dependency Positioning
-
-```mermaid
-flowchart TD
- Core["Core Init And Runtime"]
-
- Core --> Config["Configuration And Packs"]
- Core --> Logging["Logging And Query Observability"]
- Core --> Database["Database And Storage Plugins"]
- Core --> SQL["SQL Engine And Virtual Tables"]
- Core --> Events["Eventing Framework And Subscriptions"]
- Core --> Extensions["Extensions And IPC"]
-```
-
-Without this module:
-
-- No flags would be parsed
-- No plugins would activate
-- No scheduler would run
-- No graceful shutdown would occur
-
-It is the execution spine of the osquery system.
-
----
-
-## Summary
-
-The **Core Init And Runtime** module is responsible for transforming a process invocation into a fully operational, resource-governed, plugin-enabled osquery runtime.
-
-It provides:
-
-- Deterministic initialization
-- Mode-aware execution (daemon, shell, extension)
-- Resource watchdog enforcement
-- Safe shutdown semantics
-- Host identity management
-- Virtual table execution scaffolding
-
-All higher-level capabilities build on top of this foundational runtime layer.
\ No newline at end of file
diff --git a/docs/reference/architecture/core-runtime-and-lifecycle/core-runtime-and-lifecycle.md b/docs/reference/architecture/core-runtime-and-lifecycle/core-runtime-and-lifecycle.md
new file mode 100644
index 00000000000..22b49f507dc
--- /dev/null
+++ b/docs/reference/architecture/core-runtime-and-lifecycle/core-runtime-and-lifecycle.md
@@ -0,0 +1,281 @@
+# Core Runtime And Lifecycle
+
+The **Core Runtime And Lifecycle** module is responsible for bootstrapping, configuring, supervising, and gracefully shutting down the osquery process. It defines:
+
+- The global flag system and runtime configuration surface
+- Process initialization for daemon, shell, watcher, and worker modes
+- Signal handling and shutdown coordination
+- Resource limit enforcement and forced termination safeguards
+
+This module acts as the orchestration layer that connects configuration, logging, extensions, database, distributed querying, and event subsystems into a coherent runtime.
+
+---
+
+## 1. Architectural Overview
+
+At a high level, the runtime lifecycle follows this sequence:
+
+```mermaid
+flowchart TD
+ Entry["Process Entry Point"] --> Init["Initializer Constructor"]
+ Init --> ParseFlags["Parse Flags & CLI"]
+ ParseFlags --> SetupRegistry["Registry & Plugin Initialization"]
+ SetupRegistry --> ModeCheck{{"Shell / Daemon / Extension?"}}
+
+ ModeCheck -->|"Shell"| ShellInit["Shell Initialization"]
+ ModeCheck -->|"Daemon"| DaemonInit["Daemon Initialization"]
+ ModeCheck -->|"Extension"| ExtInit["Extension Initialization"]
+
+ ShellInit --> StartRuntime["Initializer.start()"]
+ DaemonInit --> StartRuntime
+ ExtInit --> StartRuntime
+
+ StartRuntime --> LoadConfig["Load Config Plugin"]
+ LoadConfig --> ActivateLogger["Activate Logger Plugin"]
+ ActivateLogger --> ActivateDistributed["Activate Distributed Plugin"]
+ ActivateDistributed --> AttachEvents["Attach Event Subscribers"]
+ AttachEvents --> Running["Runtime Active"]
+
+ Running -->|"Signal / Error"| ShutdownReq["requestShutdown()"]
+ ShutdownReq --> Graceful["Dispatcher Stop & Join"]
+ Graceful --> AlarmGuard["AlarmRunnable Guard"]
+ AlarmGuard --> Exit["Process Exit"]
+```
+
+### Key Responsibilities
+
+| Area | Responsibility |
+|------|----------------|
+| Flags | Define and track runtime options |
+| Initialization | Configure process mode and environment |
+| Plugin Activation | Select and activate config, logger, distributed plugins |
+| Watchdog Model | Supervise worker processes |
+| Shutdown | Coordinate graceful or forced termination |
+
+---
+
+## 2. Flag System
+
+**Core Components:**
+- `osquery.osquery.core.flags.FlagDetail`
+- `osquery.osquery.core.flags.FlagInfo`
+
+The flag subsystem wraps Google GFlags and adds metadata tracking specific to osquery.
+
+### 2.1 FlagDetail
+
+Defines visibility and behavioral attributes:
+
+- `description`
+- `shell` (shell-only)
+- `external` (extension-only)
+- `cli` (CLI-only, not config-settable)
+- `hidden`
+
+### 2.2 FlagInfo
+
+Provides runtime inspection data:
+
+- Type
+- Description
+- Default value
+- Current value
+- Associated `FlagDetail`
+
+### 2.3 Flag Registry
+
+All flags are tracked centrally via the `Flag` singleton:
+
+```mermaid
+flowchart LR
+ Define["FLAG Macro"] --> Create["Flag::create()"]
+ Create --> Registry["Flag Internal Map"]
+ Registry --> Query["getValue() / getType()"]
+ Registry --> Print["printFlags()"]
+```
+
+This allows:
+
+- Runtime introspection
+- Controlled updates via `updateValue()`
+- Alias support
+- Differentiation between CLI, shell, and extension flags
+
+Flags directly influence:
+
+- Plugin activation
+- Watchdog behavior
+- Database enablement
+- Distributed querying
+- OpenFrame mode activation
+
+---
+
+## 3. Process Initialization (Initializer)
+
+**Core Component:**
+- `osquery.osquery.core.init.AlarmRunnable`
+
+The `Initializer` orchestrates runtime startup. It:
+
+1. Detects tool type (shell, daemon, extension)
+2. Parses flags
+3. Initializes registries and plugins
+4. Sets up database and configuration
+5. Attaches event loops
+6. Transitions to active runtime
+
+### 3.1 Tool Modes
+
+The runtime distinguishes between:
+
+- **Shell** (`osqueryi`)
+- **Daemon** (`osqueryd`)
+- **Extension** process
+- **Watcher** (watchdog supervisor)
+- **Worker** (spawned by watcher)
+
+```mermaid
+flowchart TD
+ Initializer["Initializer"] --> Mode{{"ToolType"}}
+ Mode --> Shell["Shell Mode"]
+ Mode --> Daemon["Daemon Mode"]
+ Mode --> Extension["Extension Mode"]
+
+ Daemon --> Watchdog{{"Watchdog Enabled?"}}
+ Watchdog -->|"Yes"| Watcher["Watcher Process"]
+ Watchdog -->|"No"| DirectRun["Single Process Runtime"]
+
+ Watcher --> Worker["Worker Process"]
+```
+
+### 3.2 Watchdog Model
+
+If watchdog is enabled:
+
+- A **Watcher** supervises a **Worker** process
+- Worker executes core logic
+- Watcher restarts worker on failure
+- CPU and I/O priority adjustments are applied
+
+This model improves resilience and resource isolation.
+
+---
+
+## 4. Plugin and Subsystem Activation
+
+During `Initializer::start()`:
+
+1. Database plugin is initialized
+2. Extension manager starts
+3. Config plugin is activated
+4. Logger plugin is activated
+5. Distributed plugin is activated
+6. Event threads are attached
+
+Relevant subsystems are documented separately:
+
+- [Configuration And Packs](../configuration-and-packs/configuration-and-packs.md)
+- [Logging And Query Metadata](../logging-and-query-metadata/logging-and-query-metadata.md)
+- [SQL Engine And Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md)
+- [Database Backend](../database-backend/database-backend.md)
+- [Extensions Framework](../extensions-framework/extensions-framework.md)
+- [Events Core And Subscriptions](../events-core-and-subscriptions/events-core-and-subscriptions.md)
+- [Distributed Querying](../distributed-querying/distributed-querying.md)
+
+The Core Runtime And Lifecycle module does not implement these subsystems directly; it activates and coordinates them.
+
+---
+
+## 5. Signal Handling and Shutdown Coordination
+
+**Core Component:**
+- `osquery.osquery.core.shutdown.ShutdownData`
+
+Shutdown is centralized and thread-safe.
+
+### 5.1 ShutdownData
+
+Encapsulates:
+
+- `condition_variable` for coordination
+- `mutex` for synchronization
+- `atomic` for shutdown state
+- Exit code storage
+
+```mermaid
+flowchart TD
+ Signal["SIGTERM / SIGINT / SIGUSR1"] --> Handler["signalHandler()"]
+ Handler --> Request["requestShutdown()"]
+ Request --> Notify["Condition Variable Notify"]
+ Notify --> MainWait["waitForShutdown()"]
+ MainWait --> GracefulStop["Dispatcher::stopServices()"]
+```
+
+### 5.2 AlarmRunnable (Forced Shutdown Guard)
+
+`AlarmRunnable` runs in a separate thread during shutdown:
+
+- Waits in 200 ms intervals
+- Monitors elapsed time
+- If timeout exceeds `alarm_timeout`, calls `shutdownNow()`
+
+This prevents indefinite hangs during teardown.
+
+```mermaid
+flowchart TD
+ ShutdownStart["Initializer::shutdown()"] --> StartAlarm["Spawn AlarmRunnable"]
+ StartAlarm --> StopServices["Stop & Join Services"]
+ StopServices --> EndEvents["EventFactory::end()"]
+ EndEvents --> ShutdownDB["shutdownDatabase()"]
+ ShutdownDB --> CancelAlarm["Interrupt AlarmRunnable"]
+ CancelAlarm --> Exit["Return Exit Code"]
+```
+
+---
+
+## 6. OpenFrame Integration
+
+The module optionally enables OpenFrame mode using runtime flags:
+
+- `openframe_mode`
+- `openframe_secret`
+- `openframe_token_path`
+
+When enabled:
+
+1. Encryption service is created
+2. Token extractor retrieves initial token
+3. Authorization manager is updated
+4. Token refresher thread starts
+
+OpenFrame is initialized during startup but remains decoupled from the core lifecycle logic.
+
+---
+
+## 7. Resource Limits and Safety
+
+The initializer:
+
+- Sets file descriptor limits (POSIX)
+- Adjusts scheduling priority when watchdog is enabled
+- Supports resource limit detection via `resourceLimitHit()`
+
+If limits are exceeded, the shutdown mechanism can be triggered.
+
+---
+
+## 8. Lifecycle Summary
+
+The Core Runtime And Lifecycle module provides:
+
+- A structured startup pipeline
+- Mode-aware runtime behavior
+- Plugin activation sequencing
+- Robust shutdown guarantees
+- Watchdog-based resilience
+- Centralized flag and configuration handling
+
+It is the execution backbone of the system, ensuring that all higher-level modules operate within a controlled, observable, and recoverable runtime environment.
+
+For subsystem-specific behavior, refer to the corresponding module documentation listed above.
\ No newline at end of file
diff --git a/docs/reference/architecture/database-and-storage-plugins/database-and-storage-plugins.md b/docs/reference/architecture/database-and-storage-plugins/database-and-storage-plugins.md
deleted file mode 100644
index c3210d09ee9..00000000000
--- a/docs/reference/architecture/database-and-storage-plugins/database-and-storage-plugins.md
+++ /dev/null
@@ -1,357 +0,0 @@
-# Database And Storage Plugins
-
-## Overview
-
-The **Database And Storage Plugins** module provides the persistent and ephemeral key-value storage abstraction used by osquery core. It exposes a unified database interface that:
-
-- Persists configuration state, scheduled query metadata, event buffers, logs, and distributed query state.
-- Abstracts the underlying storage engine (e.g., RocksDB or in-memory ephemeral storage).
-- Provides safe concurrent access with reset and migration support.
-- Enables plugin-based database backends via the internal registry system.
-
-At runtime, this module acts as the storage backbone for higher-level modules such as:
-
-- [Configuration And Packs](../configuration-and-packs/configuration-and-packs.md)
-- [Logging And Query Observability](../logging-and-query-observability/logging-and-query-observability.md)
-- [Distributed Querying](../distributed-querying/distributed-querying.md)
-- [Eventing Framework And Subscriptions](../eventing-framework-and-subscriptions/eventing-framework-and-subscriptions.md)
-- [SQL Engine And Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md)
-
-It is implemented using a registry-driven plugin architecture, allowing the storage backend to be replaced or disabled.
-
----
-
-## Architectural Overview
-
-### High-Level Architecture
-
-```mermaid
-flowchart TD
- CoreModules["Core And Feature Modules"] --> DBInterface["IDatabaseInterface"]
- DBInterface --> OsqueryDB["OsqueryDatabase"]
- OsqueryDB --> RegistryLayer["Database Plugin Registry"]
- RegistryLayer --> RocksDBPlugin["RocksDB Plugin (Persistent)"]
- RegistryLayer --> EphemeralPlugin["Ephemeral Database Plugin (In-Memory)"]
-
- subgraph storage_domains["Logical Storage Domains"]
- PersistentSettings["configurations"]
- Queries["queries"]
- Events["events"]
- Logs["logs"]
- Carves["carves"]
- Distributed["distributed"]
- QueryPerformance["query_performance"]
- end
-
- RocksDBPlugin --> storage_domains
- EphemeralPlugin --> storage_domains
-```
-
-The module separates concerns into three layers:
-
-1. **Public Database Interface** β Used by the rest of the system.
-2. **Plugin Registry Layer** β Selects and manages the active database backend.
-3. **Concrete Database Plugins** β Implement actual storage logic.
-
----
-
-## Core Components
-
-### OsqueryDatabase
-
-**Component:** `osquery.osquery.database.database.OsqueryDatabase`
-
-`OsqueryDatabase` implements the `IDatabaseInterface` and serves as the primary entry point for all database operations inside osquery.
-
-It provides:
-
-- `getDatabaseValue` (string and integer variants)
-- `setDatabaseValue`
-- `setDatabaseBatch`
-- `deleteDatabaseValue`
-- `deleteDatabaseRange`
-- `scanDatabaseKeys`
-
-Internally, it delegates all operations to free functions such as:
-
-- `getDatabaseValue(...)`
-- `setDatabaseValue(...)`
-- `scanDatabaseKeys(...)`
-
-These functions:
-
-- Acquire read/write locks to protect against concurrent resets.
-- Route calls through the database plugin registry.
-- Support both internal and external (extension-based) registry execution.
-
-This design ensures that the rest of the system depends only on the interface, not the concrete backend.
-
----
-
-### EphemeralDatabasePlugin
-
-**Component:** `osquery.osquery.database.ephemeral.EphemeralDatabasePlugin`
-
-The `EphemeralDatabasePlugin` is an in-memory implementation of the `DatabasePlugin` interface.
-
-It is:
-
-- Registered internally as the `ephemeral` database plugin.
-- Used when the `disable_database` flag is enabled.
-- Used for testing and fallback scenarios.
-
-#### Internal Data Structure
-
-```mermaid
-flowchart TD
- DB["EphemeralDatabasePlugin"] --> Map["std::map>"]
- Map --> DomainMap["Domain Map"]
- DomainMap --> KeyValue["boost::variant"]
-```
-
-Storage model:
-
-- Outer map: `domain β domain_map`
-- Inner map: `key β boost::variant`
-
-Supported operations:
-
-- `get`
-- `put`
-- `putBatch`
-- `remove`
-- `removeRange`
-- `scan`
-
-Since it is purely in-memory:
-
-- No persistence across restarts.
-- No disk I/O.
-- Ideal for unit testing and ephemeral deployments.
-
----
-
-## Database Domains
-
-The module defines several logical domains used throughout osquery:
-
-| Domain | Purpose |
-|--------|----------|
-| `configurations` | Persistent settings and metadata |
-| `queries` | Scheduled query state and results metadata |
-| `events` | Event framework buffers |
-| `logs` | Buffered logging data |
-| `carves` | File carving state |
-| `distributed` | Distributed query tasks |
-| `distributed_running` | Active distributed query tracking |
-| `query_performance` | Performance metrics for queries |
-
-Domains act as logical namespaces within a single database backend.
-
----
-
-## Plugin Lifecycle and Initialization
-
-### Initialization Flow
-
-```mermaid
-flowchart TD
- Start["Startup"] --> CheckFlag{{"disable_database?"}}
- CheckFlag -->|"No"| UseRocksDB["Activate RocksDB Plugin"]
- CheckFlag -->|"Yes"| UseEphemeral["Activate Ephemeral Plugin"]
- UseRocksDB --> InitDone["Database Initialized"]
- UseEphemeral --> InitDone
-```
-
-Key behaviors:
-
-- If `disable_database` is false, the internal persistent plugin (RocksDB) is selected.
-- If `disable_database` is true, the `ephemeral` plugin is activated.
-- Initialization retries up to 25 times to handle file locks or shutdown races.
-- `kDBInitialized` ensures safe access.
-
----
-
-## Concurrency and Reset Safety
-
-To protect database operations:
-
-- A global mutex `kDatabaseReset` is used.
-- Read locks guard standard operations.
-- Write locks guard reset flows.
-
-### Reset Flow
-
-```mermaid
-flowchart TD
- ResetCall["resetDatabase()"] --> LockWrite["Acquire Write Lock"]
- LockWrite --> TearDown["Plugin tearDown()"]
- TearDown --> SetUp["Plugin setUp()"]
- SetUp --> Unlock["Release Lock"]
-```
-
-If reset fails:
-
-- The registry falls back to the `ephemeral` backend.
-- A warning is logged.
-
-This prevents total system failure when persistent storage is corrupted.
-
----
-
-## Database Migrations
-
-The module supports schema/data migrations via version tracking.
-
-- Version key: `results_version`
-- Stored under domain: `configurations`
-
-### Migration Flow
-
-```mermaid
-flowchart TD
- ReadVersion["Read results_version"] --> Compare["Compare with target version"]
- Compare -->|"Older"| RunMigration["Execute migrateVxVy()"]
- RunMigration --> UpdateVersion["Persist new version"]
- UpdateVersion --> Compare
- Compare -->|"Match"| Done["Migration Complete"]
-```
-
-Examples of migrations:
-
-- Converting legacy property-tree JSON to RapidJSON format.
-- Renaming event publisher keys.
-
-If migration fails:
-
-- Error is logged.
-- Database upgrade aborts.
-
----
-
-## Interaction with Other Modules
-
-### Configuration And Packs
-
-Configuration refreshers persist:
-
-- Pack execution counters.
-- Schedule metadata.
-- Decorator state.
-
-All stored under structured domains using `setDatabaseValue` and `scanDatabaseKeys`.
-
----
-
-### Logging And Query Observability
-
-This module persists:
-
-- Scheduled query state.
-- Query performance metrics.
-- Result differentials.
-
-The `query_performance` domain ensures metrics survive restarts when persistent storage is enabled.
-
----
-
-### Distributed Querying
-
-The distributed module uses domains:
-
-- `distributed`
-- `distributed_running`
-
-These track:
-
-- Pending tasks.
-- Active query execution state.
-
----
-
-### Eventing Framework And Subscriptions
-
-Event publishers and subscribers use the `events` domain to:
-
-- Persist event cursors.
-- Maintain audit or publisher state.
-
----
-
-## Extension and External Registry Behavior
-
-If osquery is running as an **extension process**:
-
-- It does not directly access the database backend.
-- Database requests are routed via `Registry::call("database", ...)`.
-- The main daemon handles storage.
-
-This enforces:
-
-- Centralized persistence.
-- No extension-level database corruption risk.
-
----
-
-## Key Design Characteristics
-
-### 1. Plugin-Based Storage
-
-- Storage backend selected via registry.
-- Easily replaceable or disabled.
-- Uniform request interface (`get`, `put`, `scan`, etc.).
-
-### 2. Domain Isolation
-
-Logical partitioning prevents key collisions across features.
-
-### 3. Migration Safety
-
-- Explicit version tracking.
-- Incremental migration steps.
-- Failure-safe version commit.
-
-### 4. Reset and Recovery Support
-
-- Safe reset workflow.
-- Automatic fallback to ephemeral storage.
-- Multi-attempt initialization.
-
-### 5. Thread Safety
-
-- Reader/writer locking around reset flows.
-- Atomic flags guarding initialization state.
-
----
-
-## When to Use Each Backend
-
-| Backend | Use Case |
-|----------|----------|
-| RocksDB (Persistent) | Production deployments requiring durable state |
-| Ephemeral | Testing, debugging, or stateless environments |
-
-Testing environments typically use:
-
-```text
-initDatabasePluginForTesting()
-```
-
-Which:
-
-- Forces `disable_database = true`
-- Activates ephemeral storage
-- Resets the database
-
----
-
-## Summary
-
-The **Database And Storage Plugins** module provides the foundational storage abstraction for osquery. It:
-
-- Decouples storage implementation from core logic.
-- Enables plugin-based extensibility.
-- Protects against corruption via reset and migration controls.
-- Supports both persistent and in-memory storage.
-
-Every major subsystem in osquery relies on this module for durable state, making it a critical backbone component of the overall architecture.
\ No newline at end of file
diff --git a/docs/reference/architecture/database-backend/database-backend.md b/docs/reference/architecture/database-backend/database-backend.md
new file mode 100644
index 00000000000..cadb15f5aaa
--- /dev/null
+++ b/docs/reference/architecture/database-backend/database-backend.md
@@ -0,0 +1,272 @@
+# Database Backend
+
+The **Database Backend** module provides the persistent and ephemeral keyβvalue storage layer for osquery. It abstracts the underlying storage engine behind a pluggable interface and exposes a uniform API used by configuration, logging, distributed querying, and event subsystems.
+
+At runtime, the Database Backend is responsible for:
+
+- Selecting and initializing the active database plugin (e.g., RocksDB or Ephemeral)
+- Providing domain-scoped keyβvalue operations (get, put, remove, scan)
+- Handling database resets and migrations
+- Coordinating safe access through locking and lifecycle guards
+- Offering a stable `IDatabaseInterface` for higher-level components
+
+---
+
+## 1. Architectural Overview
+
+The Database Backend sits at the core of osqueryβs state management. Other modules such as Configuration and Packs, Logging and Query Metadata, Distributed Querying, and Events rely on it for durable or transient storage.
+
+### High-Level Architecture
+
+```mermaid
+flowchart TD
+ CoreRuntime["Core Runtime and Lifecycle"] --> DatabaseBackend["Database Backend"]
+
+ DatabaseBackend --> Registry["Registry Factory"]
+ DatabaseBackend --> RocksDBPlugin["RocksDB Plugin"]
+ DatabaseBackend --> EphemeralPlugin["Ephemeral Database Plugin"]
+
+ DatabaseBackend --> ConfigModule["Configuration and Packs"]
+ DatabaseBackend --> LoggingModule["Logging and Query Metadata"]
+ DatabaseBackend --> DistributedModule["Distributed Querying"]
+ DatabaseBackend --> EventsModule["Events Core and Subscriptions"]
+```
+
+### Key Concepts
+
+- **DatabasePlugin Registry**: A registry category named `database` allows pluggable storage engines.
+- **Domains**: Logical namespaces (e.g., `queries`, `events`, `logs`) partition stored data.
+- **Global Accessors**: Helper functions (e.g., `getDatabaseValue`, `setDatabaseValue`) provide thread-safe access.
+- **Migration Framework**: Handles on-disk schema evolution between database versions.
+
+---
+
+## 2. Core Components
+
+This module contains two primary components:
+
+- `osquery.osquery.database.database.OsqueryDatabase`
+- `osquery.osquery.database.ephemeral.EphemeralDatabasePlugin`
+
+Together, they define the public database interface and a built-in in-memory implementation.
+
+---
+
+## 3. DatabasePlugin Abstraction Layer
+
+The Database Backend uses a plugin-based architecture:
+
+- A `DatabasePlugin` registry is created under the name `database`.
+- The active plugin is selected at initialization time.
+- By default, the internal RocksDB implementation is used unless disabled.
+- The Ephemeral plugin acts as a fallback or test implementation.
+
+### Initialization Flow
+
+```mermaid
+flowchart TD
+ Start["Process Startup"] --> Init["initDatabasePlugin()"]
+ Init --> CheckDisable{"disable_database flag?"}
+ CheckDisable -->|"Yes"| UseEphemeral["Set Active Plugin: Ephemeral"]
+ CheckDisable -->|"No"| UseRocksDB["Set Active Plugin: RocksDB"]
+ UseEphemeral --> MarkInit["kDBInitialized = true"]
+ UseRocksDB --> MarkInit
+ MarkInit --> Ready["Database Ready"]
+```
+
+### Concurrency Controls
+
+- `kDatabaseReset` (reader/writer mutex):
+ - **Write lock** during reset operations
+ - **Read lock** during normal get/put operations
+- Atomic flags:
+ - `kDBInitialized`
+ - `kDBAllowOpen`
+ - `kDBChecking`
+
+This ensures safe access during plugin switching, resets, and shutdown.
+
+---
+
+## 4. Domains and Data Organization
+
+The Database Backend organizes state into well-known domains:
+
+- `configurations`
+- `queries`
+- `events`
+- `logs`
+- `carves`
+- `distributed`
+- `distributed_running`
+- `query_performance`
+
+These domains are used by:
+
+- [Configuration and Packs](../configuration-and-packs/configuration-and-packs.md)
+- [Logging and Query Metadata](../logging-and-query-metadata/logging-and-query-metadata.md)
+- [Distributed Querying](../distributed-querying/distributed-querying.md)
+- [Events Core and Subscriptions](../events-core-and-subscriptions/events-core-and-subscriptions.md)
+
+Each domain is logically isolated but handled through the same plugin interface.
+
+---
+
+## 5. Public Database API
+
+The Database Backend exposes global helper functions wrapping the active plugin:
+
+- `getDatabaseValue(domain, key, value)`
+- `setDatabaseValue(domain, key, value)`
+- `setDatabaseBatch(domain, data)`
+- `deleteDatabaseValue(domain, key)`
+- `deleteDatabaseRange(domain, low, high)`
+- `scanDatabaseKeys(domain, keys, prefix, max)`
+
+### Internal Call Flow
+
+```mermaid
+flowchart TD
+ Caller["Higher Level Module"] --> Helper["getDatabaseValue()"]
+ Helper --> Lock["Acquire Read Lock"]
+ Lock --> Plugin["Active DatabasePlugin"]
+ Plugin --> Result["Return Status and Value"]
+```
+
+If running inside an **extension context**, calls are routed through the registry instead of direct plugin access, since extensions do not host active database instances.
+
+---
+
+## 6. OsqueryDatabase (IDatabaseInterface Implementation)
+
+`OsqueryDatabase` implements `IDatabaseInterface` and delegates all operations to the global helper functions.
+
+### Responsibilities
+
+- Provide a stable, dependency-injectable interface
+- Abstract away registry and plugin details
+- Support both string and integer value overloads
+
+### Delegation Pattern
+
+```mermaid
+flowchart LR
+ Client["Component Using IDatabaseInterface"] --> Interface["IDatabaseInterface"]
+ Interface --> OsqueryDB["OsqueryDatabase"]
+ OsqueryDB --> GlobalHelpers["Global Database Helpers"]
+ GlobalHelpers --> ActivePlugin["Active DatabasePlugin"]
+```
+
+This ensures that higher-level components do not depend on specific plugin implementations.
+
+---
+
+## 7. Ephemeral Database Plugin
+
+`EphemeralDatabasePlugin` is a built-in in-memory implementation of `DatabasePlugin`.
+
+### Storage Model
+
+```mermaid
+flowchart TD
+ DB["Ephemeral DB"] --> DomainMap["Map<Domain, Map<Key, Value>>"]
+ DomainMap --> KeyValue["Key -> Variant(int or string)"]
+```
+
+### Characteristics
+
+- Backed by nested `std::map` containers
+- Supports both `int` and `std::string` values via `boost::variant`
+- No persistence across restarts
+- Used for:
+ - Testing (`initDatabasePluginForTesting()`)
+ - Fallback when persistent storage fails
+ - Explicit `--disable_database` usage
+
+### Supported Operations
+
+- `get()` with type checking
+- `put()` and `putBatch()`
+- `remove()`
+- `removeRange()` with lexicographic bounds
+- `scan()` with prefix filtering and optional maximum
+
+The Ephemeral plugin is registered internally under the name `ephemeral`.
+
+---
+
+## 8. Reset, Dump, and Lifecycle
+
+### Reset Flow
+
+```mermaid
+flowchart TD
+ ResetCall["resetDatabase()"] --> RegistryCall["Registry::call action=reset"]
+ RegistryCall --> WriteLock["Acquire Write Lock"]
+ WriteLock --> TearDown["Plugin tearDown()"]
+ TearDown --> SetUp["Plugin setUp()"]
+ SetUp --> Done["Database Reinitialized"]
+```
+
+If a reset fails, the system falls back to the Ephemeral plugin.
+
+### Dumping Contents
+
+When the `database_dump` flag is enabled, all domains are scanned and printed to stdout for debugging.
+
+### Shutdown
+
+`shutdownDatabase()` removes all registered database plugins from the registry, ensuring a clean termination.
+
+---
+
+## 9. Database Versioning and Migration
+
+The Database Backend supports schema evolution via a version key stored in the `configurations` domain.
+
+- Version key: `results_version`
+- Migration path examples:
+ - V0 β V1: Convert legacy property tree JSON to RapidJSON
+ - V1 β V2: Rename specific event keys
+
+### Migration Loop
+
+```mermaid
+flowchart TD
+ Start["upgradeDatabase(target)"] --> ReadVersion["Read results_version"]
+ ReadVersion --> Compare{"Current != Target?"}
+ Compare -->|"Yes"| Migrate["Run Migration Step"]
+ Migrate --> UpdateVersion["Persist New Version"]
+ UpdateVersion --> Compare
+ Compare -->|"No"| Done["Upgrade Complete"]
+```
+
+Migration failures abort the upgrade and return an error status.
+
+---
+
+## 10. Interaction with Other Modules
+
+The Database Backend underpins several subsystems:
+
+- **Configuration and Packs**: Stores persistent configuration state and metadata.
+- **Logging and Query Metadata**: Persists query results, scheduled query counters, and performance metrics.
+- **Distributed Querying**: Tracks distributed query tasks and results.
+- **Events Core and Subscriptions**: Maintains event buffers and publisher state.
+
+It also integrates with:
+
+- **Core Runtime and Lifecycle** for startup/shutdown orchestration.
+- **Extensions Framework** for registry-based request forwarding in extension mode.
+
+---
+
+## 11. Design Strengths
+
+- β
Pluggable storage engines
+- β
Domain-based logical isolation
+- β
Thread-safe reset and access model
+- β
Backward-compatible migration framework
+- β
Extension-aware routing logic
+
+The Database Backend provides a stable foundation for osqueryβs persistent and transient state, enabling modular growth while preserving strong encapsulation and operational safety.
diff --git a/docs/reference/architecture/distributed-querying/distributed-querying.md b/docs/reference/architecture/distributed-querying/distributed-querying.md
index 37c3bf57f6c..fdbfa114ff2 100644
--- a/docs/reference/architecture/distributed-querying/distributed-querying.md
+++ b/docs/reference/architecture/distributed-querying/distributed-querying.md
@@ -1,376 +1,400 @@
# Distributed Querying
-The **Distributed Querying** module enables remote orchestration and execution of SQL queries across a fleet of osquery nodes. It allows a central server to:
+The **Distributed Querying** module enables osquery nodes to receive SQL queries from a remote service, execute them locally, and return structured results back to the requester. It acts as the orchestration layer between remote query providers (via distributed plugins), the SQL engine, the database backend, and the logging and performance subsystems.
-- Push SQL queries to enrolled agents
-- Collect query results asynchronously
-- Monitor execution performance
-- Denylist problematic or long-running queries
-
-This module acts as the execution bridge between:
-
-- The **SQL Engine and Virtual Tables** subsystem (local query execution)
-- The **Database and Storage Plugins** subsystem (state management)
-- The **Logging and Query Observability** subsystem (performance + result logging)
-- Remote transport implementations such as the TLS-based plugin
-
-At its core, Distributed Querying defines the request/response model, execution lifecycle, denylist logic, and plugin interface for retrieving and submitting distributed work.
+Unlike scheduled queries defined in configuration, distributed queries are dynamic and externally driven. This module manages their lifecycle, execution state, denylisting, performance tracking, and result serialization.
---
-## Architectural Overview
+## 1. Purpose and Responsibilities
-```mermaid
-flowchart TD
- Server["Central Server"] -->|"HTTPS"| TLSPlugin["TLS Distributed Plugin"]
- TLSPlugin -->|"getQueries()"| DistributedCore["Distributed Core"]
- DistributedCore -->|"runQueries()"| SQLEngine["SQL Engine"]
- SQLEngine -->|"QueryData"| DistributedCore
- DistributedCore -->|"writeResults()"| TLSPlugin
- TLSPlugin -->|"HTTPS"| Server
-
- DistributedCore -->|"recordQueryPerformance"| Observability["Query Observability"]
- DistributedCore -->|"running state"| Storage["Database Plugins"]
-```
+The Distributed Querying module is responsible for:
+
+- Pulling pending queries from a remote distributed plugin
+- Parsing and validating incoming work
+- Enqueuing and executing queries through the SQL engine
+- Preventing duplicate or runaway execution via denylisting
+- Tracking performance metrics per query
+- Serializing and batching results for remote delivery
+- Cleaning up expired or stale running queries
-### Key Responsibilities
+It operates as a bridge between:
-| Component | Responsibility |
-|------------|----------------|
-| Distributed Core | Lifecycle, queuing, denylisting, performance tracking |
-| Distributed Plugin | Abstract interface for remote work retrieval and result submission |
-| TLS Distributed Plugin | HTTPS implementation of Distributed Plugin |
-| SQL Engine | Executes queries against virtual tables |
-| Database Plugins | Persist running state and deduplication |
-| Observability | Tracks performance and execution metrics |
+- The Extensions Framework (plugin abstraction)
+- The SQL Engine and Virtual Tables
+- The Database Backend (state tracking)
+- Logging and Query Metadata (performance and result representation)
---
-# Core Data Structures
+## 2. Core Data Structures
-## DistributedQueryRequest
+### 2.1 DistributedQueryRequest
-Represents a single unit of distributed work.
+Represents a single distributed query instruction.
```text
Fields:
-- id: Unique server-assigned identifier
-- query: SQL string to execute
+- query : SQL string to execute
+- id : Unique identifier assigned by remote service
```
-This structure is serialized/deserialized using:
+This structure is:
-- `serializeDistributedQueryRequest`
-- `deserializeDistributedQueryRequest`
-- JSON string helpers for transport safety
+- Deserialized from plugin JSON payloads
+- Stored internally before execution
+- Attached to results for traceability
-### Example Server Payload
+Serialization and deserialization helpers:
-```json
-{
- "queries": {
- "id1": "select * from osquery_info",
- "id2": "select * from processes"
- }
-}
-```
+- serializeDistributedQueryRequest
+- serializeDistributedQueryRequestJSON
+- deserializeDistributedQueryRequest
+- deserializeDistributedQueryRequestJSON
-Each key becomes a `DistributedQueryRequest` instance.
+These ensure consistent JSON transport between node and server.
---
-## DistributedQueryResult
+### 2.2 DistributedQueryResult
-Encapsulates execution output and metadata.
+Represents the outcome of executing a distributed query.
```text
Fields:
-- request: Original DistributedQueryRequest
-- results: QueryData (rows)
-- columns: ColumnNames
-- status: Execution Status
-- message: Optional error or informational message
+- request : Original DistributedQueryRequest
+- results : QueryData (rows)
+- columns : ColumnNames
+- status : Execution Status
+- message : Additional status or error message
```
-Serialized using:
+This structure:
-- `serializeDistributedQueryResult`
-- `deserializeDistributedQueryResult`
+- Captures execution output
+- Includes metadata required by the remote server
+- Is serialized before transmission
-This object ensures transport-neutral packaging of results.
+Serialization helpers mirror those for requests:
----
+- serializeDistributedQueryResult
+- serializeDistributedQueryResultJSON
+- deserializeDistributedQueryResult
+- deserializeDistributedQueryResultJSON
-# Distributed Execution Lifecycle
+---
-The `Distributed` class orchestrates the runtime behavior.
+## 3. High-Level Architecture
```mermaid
flowchart TD
- Start["Pull Updates"] --> Accept["acceptWork()"]
- Accept --> Pending{"Pending Queries?"}
- Pending -->|"Yes"| Run["runQueries()"]
- Run --> Deny{"Denylisted?"}
- Deny -->|"No"| Execute["Execute via SQL Engine"]
- Execute --> Record["recordQueryPerformance()"]
- Record --> Queue["addResult()"]
- Queue --> Flush["flushCompleted()"]
- Deny -->|"Yes"| Skip["Skip Execution"]
- Flush --> End["Cycle Complete"]
+ RemoteService["Remote Service"] --> DistributedPlugin["Distributed Plugin"]
+ DistributedPlugin --> DistributedManager["Distributed"]
+ DistributedManager --> SQLExecutor["SQL Engine"]
+ SQLExecutor --> VirtualTables["Virtual Tables"]
+ DistributedManager --> DatabaseState["Database Backend"]
+ DistributedManager --> PerformanceTracker["Query Performance"]
+ DistributedManager --> ResultSerializer["Result Serialization"]
+ ResultSerializer --> DistributedPlugin
```
+### Components
+
+- Distributed Plugin: Provides transport abstraction (TLS or custom plugin).
+- Distributed: Core orchestration class.
+- SQL Engine: Executes SQL against virtual tables.
+- Database Backend: Tracks running and denylisted queries.
+- Query Performance: Stores execution metrics.
+
---
-## 1. Pull Phase
+## 4. DistributedPlugin Abstraction
-```cpp
-Status pullUpdates();
-```
+`DistributedPlugin` extends the generic Plugin interface and defines two core operations:
-- Calls the active `DistributedPlugin`
-- Retrieves raw JSON work payload
-- Delegates parsing to `acceptWork()`
+### 4.1 getQueries
----
+Returns JSON formatted work:
-## 2. Work Acceptance
+```text
+{
+ "queries": {
+ "id1": "select * from osquery_info",
+ "id2": "select * from processes"
+ }
+}
+```
+
+### 4.2 writeResults
+
+Accepts JSON formatted results:
-```cpp
-Status acceptWork(const std::string& work);
+```text
+{
+ "queries": {
+ "id1": [
+ {"col1": "val1"}
+ ]
+ }
+}
```
-Behavior:
+The plugin transport may use TLS, HTTP, or another extension-based mechanism. The Distributed Querying module is transport-agnostic.
+
+---
+
+## 5. Distributed Class Lifecycle
+
+The `Distributed` class manages the full query lifecycle.
-- Parses `queries` section
-- Evaluates optional `discovery` queries
-- Enqueues only valid work
+### 5.1 Continuous Execution Loop
-### Discovery Query Logic
+```mermaid
+flowchart TD
+ Start["Start Loop"] --> Pull["pullUpdates()"]
+ Pull --> Check["Pending Queries?"]
+ Check -->|"Yes"| Run["runQueries()"]
+ Check -->|"No"| Sleep["Wait Interval"]
+ Run --> Flush["flushCompleted()"]
+ Flush --> Sleep
+ Sleep --> Pull
+```
-- If no discovery query exists β enqueue
-- If discovery returns rows β enqueue
-- If discovery returns zero rows β skip
+Core public methods:
-This prevents unnecessary execution on nodes where the query is irrelevant.
+- pullUpdates
+- getPendingQueries
+- runQueries
+- serializeResults
+- getCompletedCount
+- cleanupExpiredRunningQueries
---
-## 3. Denylisting Protection
+## 6. Work Acceptance and Discovery Logic
-To prevent repeated execution of problematic queries, the module includes:
+Incoming work may include:
-- `checkAndSetAsRunning()`
-- `setAsNotRunning()`
-- `denylistedQueryTimestampExpired()`
-- `denylistDuration()`
-- `hashQuery()`
+- Direct queries
+- Discovery queries
-### Denylist Mechanism
+Discovery queries determine whether a corresponding query should run.
+
+### Discovery Behavior
```mermaid
flowchart TD
- Incoming["Incoming Query"] --> Check["checkAndSetAsRunning()"]
- Check --> Running{"Already Running?"}
- Running -->|"Within Duration"| Block["Denylisted"]
- Running -->|"Expired"| Allow["Allow Execution"]
- Check -->|"First Time"| Allow
+ ReceiveWork["acceptWork()"] --> HasDiscovery["Has Discovery Query?"]
+ HasDiscovery -->|"No"| Enqueue["Enqueue Query"]
+ HasDiscovery -->|"Yes"| RunDiscovery["Execute Discovery"]
+ RunDiscovery --> DiscoveryResult["Rows Returned?"]
+ DiscoveryResult -->|"Yes"| Enqueue
+ DiscoveryResult -->|"No"| Skip["Skip Query"]
```
-The denylist key is derived from:
+Rules:
-```text
-SHA256(query)
-```
+- No discovery query β enqueue directly
+- Discovery returns rows β enqueue
+- Discovery returns no rows β skip
-This ensures consistent identification across restarts and transports.
+This mechanism enables conditional execution across distributed fleets.
---
-## 4. Query Execution
+## 7. Execution and Denylisting
-```cpp
-Status runQueries();
-```
+To prevent duplicate or runaway queries, Distributed Querying implements a denylisting mechanism.
+
+### 7.1 Running State Tracking
-For each pending request:
+Methods:
-1. Pop request from internal storage
-2. Execute via SQL engine
-3. Measure execution time
-4. Record performance
-5. Store result
-6. Clear running state
+- checkAndSetAsRunning
+- setAsNotRunning
+- setKeyAsNotRunning
+- cleanupExpiredRunningQueries
-Execution uses:
+### 7.2 Denylist Flow
-```cpp
-SQL monitorNonnumeric(const std::string& name, const std::string& query);
+```mermaid
+flowchart TD
+ Execute["runQueries()"] --> CheckRun["checkAndSetAsRunning"]
+ CheckRun -->|"Already Running"| WithinWindow["Within Denylist Duration?"]
+ WithinWindow -->|"Yes"| Skip["Skip Execution"]
+ WithinWindow -->|"No"| ExecuteQuery["Execute Query"]
+ CheckRun -->|"Not Running"| ExecuteQuery
+ ExecuteQuery --> Complete["setAsNotRunning"]
```
----
+Supporting utilities:
-## 5. Performance Recording
+- hashQuery: SHA256 of query string
+- denylistedQueryTimestampExpired
+- denylistDuration
-Performance metrics are stored in:
+The hash is used as a stable key to track running queries across restarts and flush cycles.
-```text
-std::map performance_
-```
+---
-Tracked metrics include:
+## 8. Query Execution and Performance Monitoring
-- Execution duration
-- Row count
-- Sample process table deltas
+Queries are executed through the SQL engine using:
-These integrate with the **Logging and Query Observability** module.
+- monitorNonnumeric
+- recordQueryPerformance
----
+Performance metrics stored per query include:
-## 6. Result Flushing
+- Execution time in milliseconds
+- Number of rows returned
+- Differential row comparison (for sampled tables)
-```cpp
-Status flushCompleted();
+```mermaid
+flowchart TD
+ RunQuery["Execute SQL"] --> Measure["Measure Duration"]
+ Measure --> CountRows["Count Result Rows"]
+ CountRows --> Record["recordQueryPerformance"]
+ Record --> Store["Performance Map"]
```
-- Serializes accumulated `DistributedQueryResult` objects
-- Sends them to the plugin via `writeResults()`
-- Clears local result queue
+The performance data integrates with the broader query metadata subsystem and can influence operational visibility and diagnostics.
---
-# Plugin Interface
+## 9. Result Collection and Flushing
+
+Executed query results are appended to an internal vector:
-## DistributedPlugin (Abstract)
+```text
+std::vector results_
+```
-Defines the extension point for remote orchestration.
+### Result Handling Flow
-```cpp
-virtual Status getQueries(std::string& json) = 0;
-virtual Status writeResults(const std::string& json) = 0;
+```mermaid
+flowchart TD
+ AddResult["addResult()"] --> Buffer["results_ Vector"]
+ Buffer --> FlushCall["flushCompleted()"]
+ FlushCall --> Serialize["serializeResults()"]
+ Serialize --> PluginWrite["DistributedPlugin.writeResults()"]
+ PluginWrite --> Clear["Clear results_"]
```
-The `call()` method acts as the unified entry point for plugin requests.
+Key behavior:
-Any transport (TLS, filesystem, custom RPC) can implement this interface.
+- Results are batched
+- JSON is constructed via serialization helpers
+- Buffer is cleared after successful flush
---
-# TLS Distributed Plugin
-
-The **TLS Distributed Plugin** provides an HTTPS implementation of the plugin interface.
+## 10. Current Request Tracking
-Registered as:
+A static member tracks the ID of the currently executing distributed query:
```text
-REGISTER(TLSDistributedPlugin, "distributed", "tls")
+static std::string currentRequestId_
```
-## Configuration Flags
+Accessors:
-```text
---distributed_tls_read_endpoint
---distributed_tls_write_endpoint
---distributed_tls_max_attempts
-```
+- getCurrentRequestId
+- setCurrentRequestId
-## Setup Phase
+This enables:
-```cpp
-Status setUp();
-```
+- Correlation with logs
+- Traceability in error handling
+- Integration with logging and metadata subsystems
-- Builds read/write URIs
-- Uses TLS request helper utilities
+---
-## Query Retrieval
+## 11. Interaction with Other Modules
-```cpp
-Status getQueries(std::string& json);
-```
+Distributed Querying interacts closely with several major subsystems:
-- Sends POST to read endpoint
-- Returns JSON payload containing work
+### SQL Engine and Virtual Tables
-## Result Submission
+- Executes distributed SQL statements
+- Retrieves rows from virtual tables
+- Uses SQL abstraction for safe execution
-```cpp
-Status writeResults(const std::string& json);
-```
+### Database Backend
-- Parses JSON
-- POSTs to write endpoint
-- Ignores server response body
+- Tracks running query keys
+- Maintains denylist timestamps
+- Persists state across iterations
----
+### Logging and Query Metadata
-## TLS Data Flow
+- Records performance metrics
+- Associates status and message fields with results
+- Enables operational insight
-```mermaid
-sequenceDiagram
- participant Node
- participant TLS as "TLS Distributed Plugin"
- participant Server
-
- Node->>TLS: pullUpdates()
- TLS->>Server: POST read endpoint
- Server->>TLS: JSON queries
- TLS->>Node: return JSON
- Node->>TLS: writeResults(JSON)
- TLS->>Server: POST write endpoint
-```
+### Extensions Framework
+
+- Provides Plugin abstraction
+- Allows pluggable distributed transports
+- Supports external TLS-based or custom implementations
---
-# State Management
+## 12. End-to-End Data Flow
-Distributed Querying relies on persistent state to:
+```mermaid
+flowchart TD
+ Server["Remote Server"] --> PluginPull["getQueries()"]
+ PluginPull --> Accept["acceptWork()"]
+ Accept --> Queue["Internal Queue"]
+ Queue --> Execute["runQueries()"]
+ Execute --> SQL["SQL Engine"]
+ SQL --> Results["DistributedQueryResult"]
+ Results --> Buffer["results_"]
+ Buffer --> Flush["flushCompleted()"]
+ Flush --> PluginPush["writeResults()"]
+ PluginPush --> Server
+```
-- Track running queries
-- Store denylist timestamps
-- Maintain queued work
+This flow illustrates the complete lifecycle:
-This state is handled through the Database and Storage Plugins subsystem.
+1. Remote server issues queries
+2. Node pulls and parses work
+3. Queries are conditionally enqueued
+4. SQL execution occurs
+5. Results are serialized
+6. Results are flushed back to server
---
-# Security Model
-
-Key security properties:
+## 13. Design Characteristics
-1. Query integrity validated via SHA-256 hashing
-2. HTTPS transport in TLS plugin
-3. Configurable retry attempts
-4. Denylist prevents execution storms
+### Transport Agnostic
-The denylist duration is configurable via runtime flags.
+The module does not embed networking logic. All communication is delegated to DistributedPlugin implementations.
----
+### Safe Execution
-# Integration Points
+- Denylisting prevents duplicate execution storms
+- Hash-based tracking ensures stable identity
+- Expired running queries are cleaned automatically
-Distributed Querying integrates with:
+### Observability-Oriented
-- SQL Engine and Virtual Tables (local execution)
-- Database and Storage Plugins (persistent state)
-- Logging and Query Observability (performance tracking)
-- Extensions and IPC (optional distributed plugin implementations)
-- Remote HTTP Client (transport layer headers and networking)
+- Query performance metrics are recorded
+- Status and error messages are preserved
+- Current request ID enables traceability
-Sibling module reference:
+### Scalable by Design
-- [Remote HTTP Client](../remote-http-client/remote-http-client.md)
+- Pull-based model supports fleet scaling
+- Batched result submission reduces overhead
+- Discovery queries minimize unnecessary work
---
# Summary
-The **Distributed Querying** module provides:
-
-- A structured request/response model
-- Pluggable transport abstraction
-- Controlled query lifecycle management
-- Built-in denylisting and performance tracking
-- Secure TLS-based remote orchestration
+The **Distributed Querying** module orchestrates remote query execution across osquery nodes. It abstracts transport through plugins, enforces safe execution with denylisting, integrates tightly with the SQL engine and database backend, and provides structured, serialized results enriched with performance metadata.
-It transforms osquery from a local query engine into a centrally orchestrated distributed telemetry system while preserving execution safety and observability guarantees.
+It is the core execution engine for dynamic, centrally managed queries in distributed deployments.
\ No newline at end of file
diff --git a/docs/reference/architecture/distributed-tls-plugin/distributed-tls-plugin.md b/docs/reference/architecture/distributed-tls-plugin/distributed-tls-plugin.md
new file mode 100644
index 00000000000..0f8f43f50c6
--- /dev/null
+++ b/docs/reference/architecture/distributed-tls-plugin/distributed-tls-plugin.md
@@ -0,0 +1,287 @@
+# Distributed Tls Plugin
+
+The **Distributed Tls Plugin** module implements the TLS-based distributed query transport for osquery. It enables secure retrieval of distributed queries from a remote service and submission of query results back to that service over HTTPS.
+
+This module provides a concrete implementation of the distributed plugin interface and acts as the secure bridge between the local distributed query engine and a remote TLS endpoint.
+
+---
+
+## Purpose and Responsibilities
+
+The Distributed Tls Plugin is responsible for:
+
+- Retrieving distributed queries from a remote HTTPS endpoint
+- Submitting distributed query results back to a remote HTTPS endpoint
+- Handling retry logic for network communication
+- Serializing and deserializing JSON payloads
+- Integrating with the enrollment and TLS transport stack
+
+It extends the distributed query abstraction defined in the [Distributed Querying](distributed-querying/distributed-querying.md) module and relies on the TLS transport utilities provided by the remote HTTP layer.
+
+---
+
+## Core Component
+
+### TLSDistributedPlugin
+
+**Namespace:** `osquery.plugins.distributed.tls_distributed`
+
+The `TLSDistributedPlugin` class derives from `DistributedPlugin` and is registered under the name:
+
+- Registry type: `distributed`
+- Plugin name: `tls`
+
+This makes it selectable as the distributed backend when TLS-based communication is desired.
+
+### Key Methods
+
+- `setUp()` β Initializes TLS endpoints
+- `getQueries(std::string& json)` β Fetches distributed queries from remote server
+- `writeResults(const std::string& json)` β Submits query results to remote server
+
+---
+
+## Configuration Flags
+
+The Distributed Tls Plugin is configured using runtime flags:
+
+- `distributed_tls_read_endpoint` β HTTPS endpoint for retrieving queries
+- `distributed_tls_write_endpoint` β HTTPS endpoint for submitting results
+- `distributed_tls_max_attempts` β Maximum retry attempts for requests
+- `tls_node_api` β Enables node-specific TLS behavior
+
+These flags are part of the runtime configuration system described in the Core Runtime and Lifecycle module.
+
+---
+
+## Architectural Position
+
+The Distributed Tls Plugin sits between the distributed query engine and the remote HTTPS service.
+
+```mermaid
+flowchart LR
+ DistributedEngine["Distributed Query Engine"] -->|"getQueries()"| TLSPlugin["Distributed Tls Plugin"]
+ TLSPlugin -->|"HTTPS POST"| RemoteServer["Remote TLS Server"]
+ RemoteServer -->|"JSON Queries"| TLSPlugin
+ TLSPlugin -->|"writeResults()"| DistributedEngine
+```
+
+### Relationships
+
+- **Upstream Dependency:** [Distributed Querying](distributed-querying/distributed-querying.md)
+- **Transport Layer:** Remote HTTP client and TLS request utilities
+- **Serialization:** JSON serializer
+- **Enrollment:** Integrates with node identity and enrollment utilities
+
+---
+
+## Internal Flow
+
+### Setup Phase
+
+During initialization:
+
+1. Read endpoint flags are retrieved
+2. URIs are constructed using TLS helpers
+3. Internal read and write URIs are stored
+
+```mermaid
+flowchart TD
+ Start["Start setUp()"] --> ReadFlag["Read distributed_tls_read_endpoint"]
+ ReadFlag --> MakeReadURI["TLSRequestHelper makeURI()"]
+ MakeReadURI --> WriteFlag["Read distributed_tls_write_endpoint"]
+ WriteFlag --> MakeWriteURI["TLSRequestHelper makeURI()"]
+ MakeWriteURI --> StoreURIs["Store read_uri and write_uri"]
+ StoreURIs --> EndNode["END"]
+```
+
+---
+
+### Query Retrieval Flow
+
+The `getQueries()` method performs a POST request to retrieve distributed queries.
+
+```mermaid
+sequenceDiagram
+ participant Engine
+ participant TLSPlugin
+ participant TLSTransport
+ participant Remote
+ Engine->>TLSPlugin: getQueries()
+ TLSPlugin->>TLSTransport: go(JSONSerializer)
+ TLSTransport->>Remote: HTTPS POST read_uri
+ Remote-->>TLSTransport: JSON query payload
+ TLSTransport-->>TLSPlugin: Serialized JSON
+ TLSPlugin-->>Engine: Query JSON
+```
+
+### Key Characteristics
+
+- Always uses HTTP POST
+- Serializes parameters using JSON
+- Retries up to configured maximum attempts
+- Returns raw JSON payload to distributed engine
+
+---
+
+### Result Submission Flow
+
+The `writeResults()` method submits distributed query results.
+
+```mermaid
+flowchart TD
+ StartWrite["Start writeResults()"] --> ParseJSON["Parse input JSON"]
+ ParseJSON --> ValidCheck{{"Valid JSON?"}}
+ ValidCheck -->|"No"| ReturnError["Return error Status"]
+ ValidCheck -->|"Yes"| SendTLS["TLSRequestHelper go()"]
+ SendTLS --> IgnoreResp["Ignore server response"]
+ IgnoreResp --> EndWrite["END"]
+```
+
+### Important Behavior
+
+- Validates JSON before transmission
+- Uses the write endpoint
+- Ignores server response body
+- Returns status of TLS request operation
+
+---
+
+## Interaction with Distributed Querying Module
+
+The Distributed Tls Plugin implements the transport layer for the distributed query lifecycle:
+
+```mermaid
+flowchart LR
+ Scheduler["Distributed Scheduler"] --> Request["DistributedQueryRequest"]
+ Request --> TLSPlugin["Distributed Tls Plugin"]
+ TLSPlugin --> Result["DistributedQueryResult"]
+ Result --> Scheduler
+```
+
+The data structures used by this plugin originate from the [Distributed Querying](distributed-querying/distributed-querying.md) module:
+
+- `DistributedQueryRequest`
+- `DistributedQueryResult`
+
+The plugin itself does not interpret SQL; it only transports JSON payloads.
+
+---
+
+## Retry and Error Handling
+
+The plugin delegates network execution to `TLSRequestHelper::go()` which:
+
+- Performs HTTPS communication
+- Applies retry logic
+- Uses the configured maximum attempt count
+- Returns a `Status` object
+
+```mermaid
+flowchart TD
+ StartRetry["Start TLS request"] --> Attempt["Attempt HTTPS call"]
+ Attempt --> SuccessCheck{{"Success?"}}
+ SuccessCheck -->|"Yes"| ReturnOK["Return Status OK"]
+ SuccessCheck -->|"No"| RetryCheck{{"Attempts left?"}}
+ RetryCheck -->|"Yes"| Attempt
+ RetryCheck -->|"No"| ReturnFail["Return Status Error"]
+```
+
+This separation ensures:
+
+- Clean transport abstraction
+- Centralized TLS handling
+- Consistent retry semantics across plugins
+
+---
+
+## Security Considerations
+
+The Distributed Tls Plugin relies on:
+
+- HTTPS transport
+- TLS certificate validation
+- Enrollment identity
+- Secure JSON serialization
+
+Security is enforced at the TLS transport layer rather than inside the plugin itself.
+
+Key security characteristics:
+
+- No plaintext query transport
+- No local storage of distributed results
+- No custom cryptographic implementation
+- Delegation to hardened TLS transport utilities
+
+---
+
+## Registry Integration
+
+The plugin is registered using the osquery registry system:
+
+- Registry category: `distributed`
+- Plugin name: `tls`
+
+This allows dynamic selection of distributed backends at runtime.
+
+```mermaid
+flowchart LR
+ Registry["Registry"] --> DistributedCategory["distributed Category"]
+ DistributedCategory --> TLSPlugin["tls Plugin"]
+```
+
+The registry framework is defined in the broader core runtime and extension infrastructure.
+
+---
+
+## Data Contracts
+
+The plugin communicates exclusively via JSON.
+
+### Incoming (Query Retrieval)
+
+- JSON payload containing distributed queries
+- Delivered as raw JSON string to the distributed engine
+
+### Outgoing (Result Submission)
+
+- JSON representation of distributed query results
+- Must parse successfully before transmission
+
+No SQL parsing, validation, or transformation occurs inside this module.
+
+---
+
+## Integration with Other Modules
+
+The Distributed Tls Plugin integrates with:
+
+- [Distributed Querying](distributed-querying/distributed-querying.md) β Defines distributed query structures and lifecycle
+- Remote HTTP client utilities β Provides TLS transport and request helpers
+- Core runtime flags system β Supplies configuration values
+
+It does not:
+
+- Execute SQL (handled by SQL engine modules)
+- Persist results (handled by database backend modules)
+- Schedule queries (handled by distributed engine and scheduler)
+
+---
+
+## Design Principles
+
+The Distributed Tls Plugin follows several architectural principles:
+
+1. **Single Responsibility** β Only handles TLS-based distributed transport
+2. **Transport Abstraction** β Delegates networking to TLS helpers
+3. **Stateless Operation** β No persistent internal state beyond URIs
+4. **Retry Delegation** β Centralized retry logic in transport layer
+5. **JSON Boundary** β Uses JSON as strict interface contract
+
+---
+
+## Summary
+
+The **Distributed Tls Plugin** is the secure transport implementation for distributed queries over HTTPS. It connects the distributed query engine to a remote control plane, handling retrieval and submission of query data through TLS-protected endpoints.
+
+By isolating network communication from query execution and scheduling logic, it maintains a clean separation of concerns while enabling secure, scalable distributed query workflows.
\ No newline at end of file
diff --git a/docs/reference/architecture/eventing-framework-and-subscriptions/eventing-framework-and-subscriptions.md b/docs/reference/architecture/eventing-framework-and-subscriptions/eventing-framework-and-subscriptions.md
deleted file mode 100644
index a18e9b822dc..00000000000
--- a/docs/reference/architecture/eventing-framework-and-subscriptions/eventing-framework-and-subscriptions.md
+++ /dev/null
@@ -1,363 +0,0 @@
-# Eventing Framework And Subscriptions
-
-## Overview
-
-The **Eventing Framework And Subscriptions** module provides the core publish/subscribe infrastructure for osqueryβs event-driven data model. It enables:
-
-- Event publishers to monitor operating system activity (e.g., file changes, process activity).
-- Event subscribers to register interest in specific event types.
-- Persistent storage of event data for later retrieval via virtual tables.
-- Automatic lifecycle, expiration, and optimization of event data based on query schedules.
-
-This module acts as the bridge between:
-
-- The SQL Engine And Virtual Tables module (which exposes event tables to queries).
-- The Database And Storage Plugins module (which persists event data).
-- The Configuration And Packs module (which defines scheduled queries and event usage).
-
----
-
-## High-Level Architecture
-
-```mermaid
-flowchart TD
- Config["Configuration And Packs"] -->|"scheduled queries"| EventFactory["EventFactory"]
- EventFactory -->|"registers"| Publisher["EventPublisherPlugin"]
- EventFactory -->|"registers"| Subscriber["EventSubscriberPlugin"]
- Subscriber -->|"creates"| SubscriptionObj["Subscription"]
- Publisher -->|"dispatches"| Callback["EventCallback"]
- Callback -->|"addBatch()"| Storage["Database And Storage Plugins"]
- SQL["SQL Engine And Virtual Tables"] -->|"SELECT from _events tables"| Subscriber
- Subscriber -->|"generateRows()"| SQL
-```
-
-### Core Roles
-
-- **EventFactory** β Central coordinator for publishers and subscribers.
-- **EventPublisherPlugin** β Produces system events.
-- **EventSubscriberPlugin** β Consumes events and exposes them as queryable tables.
-- **Subscription** β Binds subscriber logic to publisher events.
-- **PathSet utilities** β Optimized path pattern matching for filesystem-related subscriptions.
-
----
-
-## EventFactory
-
-The `EventFactory` is a singleton responsible for managing the lifecycle and coordination of all event publishers and subscribers.
-
-### Responsibilities
-
-- Registering and deregistering event publishers and subscribers.
-- Creating and forwarding subscriptions.
-- Spawning publisher run-loop threads.
-- Coordinating shutdown and cleanup.
-- Applying configuration updates (e.g., scheduled query analysis).
-
-### Publisher and Subscriber Registration
-
-```mermaid
-flowchart TD
- RegisterSub["registerEventSubscriber()"] --> SetupSub["setUp()"]
- SetupSub --> InitSub["init()"]
- InitSub --> RunningSub["EVENT_RUNNING"]
-
- RegisterPub["registerEventPublisher()"] --> SetupPub["setUp()"]
- SetupPub --> ReadyPub["EVENT_SETUP"]
-```
-
-During registration:
-
-- Subscribers are optionally enabled/disabled via configuration (`events.enable_subscribers`, `events.disable_subscribers`).
-- Publishers are validated by type and initialized if events are enabled.
-- State transitions are enforced (`EVENT_NONE`, `EVENT_SETUP`, `EVENT_RUNNING`, `EVENT_PAUSED`, `EVENT_FAILED`).
-
-### Publisher Execution Model
-
-Each publisher runs in its own thread:
-
-```mermaid
-flowchart TD
- Delay["delay()"] --> ThreadSpawn["spawn thread per publisher"]
- ThreadSpawn --> RunLoop["run(type_id)"]
- RunLoop --> PublisherRun["publisher->run()"]
- PublisherRun --> Pause["pause(200ms)"]
- Pause --> RunLoop
- RunLoop -->|"isEnding()"| TearDown["tearDown()"]
-```
-
-Key behaviors:
-
-- The factory prevents publisher restarts once started.
-- A default cool-off pause avoids CPU thrashing.
-- Shutdown via `end()` gracefully deregisters publishers and joins threads.
-
----
-
-## Subscription Model
-
-The `Subscription` structure binds a subscriber to a publisher.
-
-### Subscription Structure
-
-```text
-Subscription
- βββ subscriber_name
- βββ context (SubscriptionContextRef)
- βββ callback (EventCallback)
-```
-
-Defined in:
-
-- `osquery.osquery.events.subscription.Subscription`
-
-### EventCallback
-
-```text
-Status(const EventContextRef&, const SubscriptionContextRef&)
-```
-
-When an event fires:
-
-1. The publisher evaluates matching subscriptions.
-2. The associated callback executes.
-3. The subscriber stores structured rows using `addBatch()`.
-
-Subscriptions are usually created via:
-
-```cpp
-EventFactory::addSubscription("PublisherType", subscription);
-```
-
----
-
-## EventSubscriberPlugin
-
-Defined in:
-
-- `osquery.osquery.events.eventsubscriberplugin.Context`
-- `osquery.osquery.events.eventsubscriberplugin.GenerateRowsResult`
-
-The `EventSubscriberPlugin` class encapsulates event storage, indexing, expiration, and query-time retrieval.
-
-### Core Responsibilities
-
-- Registering subscriptions in `init()`.
-- Storing events using `addBatch()`.
-- Managing time-based indexing and expiration.
-- Exposing events as virtual tables via `genTable()`.
-
-### Internal Context
-
-```text
-Context
- βββ database_namespace
- βββ event_index
- βββ last_query_time
- βββ last_event_id
-```
-
-The context ensures:
-
-- Namespace isolation between subscribers.
-- Efficient indexing by time and event identifier.
-- Thread-safe updates using mutexes.
-
-### Event Storage and Expiration
-
-```mermaid
-flowchart TD
- Callback["EventCallback"] --> AddBatch["addBatch()"]
- AddBatch --> AssignID["generateEventIdentifier()"]
- AssignID --> Persist["Database write"]
- Persist --> IndexUpdate["update time index"]
-
- ExpireCheck["expireEventBatches()"] --> RemoveOld["delete expired batches"]
-```
-
-Expiration behavior is governed by:
-
-- `getEventsExpiry()` β Default from flags.
-- `getEventBatchesMax()` β Max retained batches.
-- `setMinExpiry()` β Adjusted dynamically based on scheduled query intervals.
-
-### Query-Time Retrieval
-
-When a query selects from an event table:
-
-```mermaid
-flowchart TD
- SQLQuery["SELECT * FROM example_events"] --> GenTable["genTable()"]
- GenTable --> GenerateRows["generateRows()"]
- GenerateRows --> FilterTime["apply start/stop window"]
- FilterTime --> YieldRows["yield Row to SQL engine"]
-```
-
-The `GenerateRowsResult` structure tracks:
-
-- Whether the scan reached the end.
-- The last processed timestamp.
-- The last processed event identifier.
-
-This enables optimized incremental queries.
-
----
-
-## Configuration-Driven Expiration Logic
-
-One of the most advanced responsibilities of this module is aligning event retention with scheduled queries.
-
-### SubscriberExpirationDetails
-
-Defined in:
-
-- `osquery.osquery.events.eventfactory.SubscriberExpirationDetails`
-
-Structure:
-
-```text
-SubscriberExpirationDetails
- βββ max_interval
- βββ query_count
-```
-
-During `configUpdate()`:
-
-1. The schedule is scanned for queries referencing `_events` tables.
-2. For each subscriber table:
- - The maximum interval is recorded.
- - The number of queries referencing it is counted.
-3. The minimum expiration window is set to:
-
-```text
-min_expiry = (max_interval * 3), rounded to next minute
-```
-
-This ensures:
-
-- Events are retained long enough for scheduled queries to observe them.
-- Storage is not retained unnecessarily.
-
----
-
-## PathSet and Pattern Matching
-
-Defined in:
-
-- `osquery.osquery.events.pathset.Compare`
-
-The `PathSet` template provides a thread-safe multiset implementation for path-based matching.
-
-### Supported Patterns
-
-- `*` β Match a single path component.
-- `**` β Recursive wildcard.
-
-Example equivalence:
-
-```text
-/This/Path/is
-/This/Path/*
-/This/Path/**
-```
-
-### Comparison Logic
-
-The `Compare` functor:
-
-- Compares path components lexicographically.
-- Treats `*` as a wildcard.
-- Treats `**` as recursive match.
-- Maintains ordering semantics required by `std::multiset`.
-
-This is especially important for filesystem event publishers that need efficient path matching across many subscriptions.
-
----
-
-## Concurrency Model
-
-```mermaid
-flowchart LR
- FactoryLock["factory_lock_"] --> ProtectPub["event_pubs_"]
- FactoryLock --> ProtectSub["event_subs_"]
-
- SubscriberLock1["event_id_lock_"] --> IDGen["EventID generation"]
- SubscriberLock2["event_record_lock_"] --> RecordWrite["record time bins"]
- SubscriberLock3["event_query_record_"] --> QueryTracking["query usage tracking"]
-```
-
-Key thread-safety mechanisms:
-
-- Recursive locks in `EventFactory`.
-- Mutex-protected event indexing.
-- Atomic counters for event identifiers and expiration windows.
-- Dedicated threads per publisher.
-
----
-
-## Integration With Other Modules
-
-### SQL Engine And Virtual Tables
-
-- Event subscribers expose data through `genTable()`.
-- `_events` tables are queried like normal virtual tables.
-
-### Database And Storage Plugins
-
-- Event rows are persisted using `IDatabaseInterface`.
-- Time-based indexing enables efficient windowed queries.
-
-### Configuration And Packs
-
-- Scheduled queries determine retention windows.
-- Config parsers can enable/disable subscribers.
-
-### Logging And Query Observability
-
-- Events may be forwarded using `addForwarder()` and `forwardEvent()`.
-- Logger plugins can receive structured event payloads.
-
----
-
-## End-to-End Flow
-
-```mermaid
-sequenceDiagram
- participant Config
- participant Factory as EventFactory
- participant Pub as EventPublisher
- participant Sub as EventSubscriber
- participant DB as Database
- participant SQL
-
- Config->>Factory: configUpdate()
- Factory->>Sub: setMinExpiry()
- Factory->>Pub: spawn run loop
- Pub->>Sub: fire event (callback)
- Sub->>DB: addBatch()
- SQL->>Sub: SELECT from event table
- Sub->>DB: generateRows()
- Sub->>SQL: yield rows
-```
-
----
-
-## Design Principles
-
-1. **Separation of Concerns** β Publishers generate, subscribers transform and persist, SQL retrieves.
-2. **Config-Aware Retention** β Event expiration adapts to scheduled queries.
-3. **Thread Isolation** β Each publisher runs independently.
-4. **Optimized Query Windows** β Incremental scanning via time and ID indexes.
-5. **Extensibility** β New publishers and subscribers can be registered dynamically.
-
----
-
-## Summary
-
-The **Eventing Framework And Subscriptions** module is the backbone of osqueryβs event-driven capabilities. It provides:
-
-- A robust publish/subscribe infrastructure.
-- Persistent and optimized event storage.
-- Config-driven lifecycle management.
-- Tight integration with the SQL engine and scheduler.
-
-Through careful coordination between `EventFactory`, `EventSubscriberPlugin`, `Subscription`, and `PathSet`, this module enables scalable, queryable system event monitoring across platforms.
\ No newline at end of file
diff --git a/docs/reference/architecture/events-core-and-subscriptions/events-core-and-subscriptions.md b/docs/reference/architecture/events-core-and-subscriptions/events-core-and-subscriptions.md
new file mode 100644
index 00000000000..e52aa39dbbc
--- /dev/null
+++ b/docs/reference/architecture/events-core-and-subscriptions/events-core-and-subscriptions.md
@@ -0,0 +1,316 @@
+# Events Core And Subscriptions
+
+The **Events Core And Subscriptions** module implements the publish/subscribe eventing infrastructure used by osquery to collect, persist, and expose real-time and near-real-time system events as virtual tables.
+
+It connects:
+
+- **Event publishers** (low-level OS or subsystem monitors)
+- **Event subscribers** (table-oriented processors of events)
+- **Subscriptions** (scoped event filters and callbacks)
+- **Persistent storage and expiration logic**
+
+This module is the backbone of event-based tables (e.g., file events, process events) and integrates tightly with:
+
+- [Configuration And Packs](../configuration-and-packs/configuration-and-packs.md)
+- [SQL Engine And Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md)
+- [Database Backend](../database-backend/database-backend.md)
+- [Logging And Query Metadata](../logging-and-query-metadata/logging-and-query-metadata.md)
+
+---
+
+## 1. Architectural Overview
+
+The module implements a centralized **EventFactory** that coordinates publishers and subscribers.
+
+```mermaid
+flowchart TD
+ Config["Configuration And Packs"] -->|"scheduled queries"| EventFactory["EventFactory"]
+
+ subgraph publishers["Event Publishers"]
+ Pub1["EventPublisherPlugin"]
+ end
+
+ subgraph subscribers["Event Subscribers"]
+ Sub1["EventSubscriberPlugin"]
+ end
+
+ EventFactory -->|"register"| Pub1
+ EventFactory -->|"register"| Sub1
+
+ Sub1 -->|"create"| Subscription["Subscription"]
+ Subscription -->|"attach"| Pub1
+
+ Pub1 -->|"fires events"| Sub1
+ Sub1 -->|"persist rows"| DB["Database Backend"]
+ Sub1 -->|"expose table"| SQL["SQL Engine And Virtual Tables"]
+```
+
+### Core Responsibilities
+
+| Component | Responsibility |
+|------------|---------------|
+| EventFactory | Lifecycle and orchestration of publishers and subscribers |
+| EventSubscriberPlugin | Consumes events and persists them as table rows |
+| Subscription | Binds a subscriber callback to publisher-specific criteria |
+| Context | Maintains indexing and namespace state |
+| GenerateRowsResult | Supports optimized time-bounded table scans |
+
+---
+
+## 2. EventFactory
+
+The **EventFactory** is a singleton that manages:
+
+- Publisher registration
+- Subscriber registration
+- Subscription routing
+- Thread lifecycle for publishers
+- Schedule-driven expiration tuning
+
+### 2.1 Registration Flow
+
+```mermaid
+flowchart TD
+ RegisterSub["registerEventSubscriber()"] --> Setup["setUp()"]
+ Setup --> Init["init()"]
+ Init --> Running["EVENT_RUNNING"]
+
+ RegisterPub["registerEventPublisher()"] --> PubSetup["publisher.setUp()"]
+ PubSetup --> Stored["stored in factory map"]
+```
+
+Key behaviors:
+
+- Validates plugin type
+- Applies configuration-based enable/disable rules
+- Transitions subscriber state (`EVENT_SETUP`, `EVENT_RUNNING`, `EVENT_PAUSED`, `EVENT_FAILED`)
+- Prevents duplicate publisher types
+
+### 2.2 Subscription Routing
+
+Subscriptions are added via:
+
+- `EventFactory::addSubscription(type_id, name_id, context, callback)`
+- Routed to the appropriate publisher
+
+If the publisher does not exist, the operation fails safely.
+
+### 2.3 Publisher Execution Model
+
+Each publisher runs inside its own thread.
+
+```mermaid
+flowchart TD
+ Delay["EventFactory.delay()"] --> Spawn["spawn thread per publisher"]
+ Spawn --> RunLoop["EventFactory.run(type)"]
+ RunLoop --> Loop["publisher.run() loop"]
+ Loop --> Pause["pause 200ms"]
+ Loop -->|"error"| TearDown["tearDown()"]
+```
+
+Important behaviors:
+
+- Publishers cannot be restarted once started
+- Controlled shutdown via `isEnding()`
+- Automatic teardown on loop exit
+- Threads joined or detached via `end(join)`
+
+---
+
+## 3. EventSubscriberPlugin
+
+`EventSubscriberPlugin` is the abstraction that:
+
+- Registers subscriptions during `init()`
+- Receives events via callbacks
+- Converts them into `Row` objects
+- Persists them in the backing database
+- Serves them through `genTable()`
+
+### 3.1 Internal Context
+
+Each subscriber maintains a `Context`:
+
+```mermaid
+flowchart TD
+ Context["Context"] --> Namespace["database_namespace"]
+ Context --> Index["event_index"]
+ Context --> LastTime["last_query_time"]
+ Context --> LastEvent["last_event_id"]
+```
+
+The context ensures:
+
+- Namespace isolation between subscribers
+- Unique event identifiers
+- Optimized time-based indexing
+- Safe concurrency via mutexes
+
+### 3.2 Event Storage Flow
+
+When an event fires:
+
+```mermaid
+flowchart TD
+ Publisher["EventPublisher"] --> Callback["EventCallback"]
+ Callback --> AddBatch["addBatch(rows)"]
+ AddBatch --> DBWrite["Database Backend"]
+```
+
+Key concepts:
+
+- `addBatch()` is preferred over deprecated `add()`
+- Events are indexed by time and EventID
+- Expiration and overflow enforcement applied
+
+### 3.3 Query-Time Retrieval
+
+At SQL execution time:
+
+```mermaid
+flowchart TD
+ SQLQuery["SELECT * FROM event_table"] --> GenTable["genTable()"]
+ GenTable --> GenerateRows["generateRows()"]
+ GenerateRows --> Filter["time window filtering"]
+ Filter --> Yield["RowYield callback"]
+```
+
+`GenerateRowsResult` provides:
+
+- `isEnd` flag
+- `last_time`
+- `last_id`
+
+This supports incremental and optimized scans.
+
+---
+
+## 4. Subscription
+
+A **Subscription** binds:
+
+- A subscriber name
+- A publisher-specific context
+- A callback
+
+```mermaid
+flowchart LR
+ Sub["EventSubscriber"] -->|"creates"| Subscription
+ Subscription -->|"context + callback"| Publisher
+ Publisher -->|"fires"| Callback
+```
+
+### Structure
+
+| Field | Purpose |
+|--------|--------|
+| subscriber_name | Identifies subscriber |
+| context | Publisher-specific filter configuration |
+| callback | Event processing function |
+
+Subscriptions:
+
+- Scope publisher workload
+- Allow fine-grained filtering
+- Decouple publishers from subscriber logic
+
+---
+
+## 5. Schedule-Aware Expiration Logic
+
+The module dynamically adjusts expiration windows based on scheduled queries.
+
+During `configUpdate()`:
+
+1. All scheduled queries are scanned.
+2. Queries referencing `_events` tables are identified.
+3. Per-subscriber metrics are computed:
+ - Maximum interval
+ - Query count
+4. Minimum expiration is set to `max_interval * 3`, rounded to minute boundary.
+
+```mermaid
+flowchart TD
+ Scheduled["Scheduled Queries"] --> Scan["scan for event tables"]
+ Scan --> Compute["compute max interval + count"]
+ Compute --> SetExpiry["setMinExpiry()"]
+ SetExpiry --> ResetCount["resetQueryCount()"]
+```
+
+This ensures:
+
+- Data persists long enough for slow schedules
+- Subscribers expire events safely
+- Over-aggressive expiration is prevented
+
+---
+
+## 6. Forwarding and Logging Integration
+
+EventFactory supports forwarding serialized events to logger plugins:
+
+- `addForwarder(logger_name)`
+- `forwardEvent(event_string)`
+
+This integrates with:
+
+- [Logging And Query Metadata](../logging-and-query-metadata/logging-and-query-metadata.md)
+
+Allowing event streams to be:
+
+- Logged
+- Forwarded to remote systems
+- Integrated with distributed pipelines
+
+---
+
+## 7. Lifecycle Summary
+
+```mermaid
+flowchart TD
+ Start["Startup"] --> Register["Register Publishers & Subscribers"]
+ Register --> Config["Apply Config Enable/Disable"]
+ Config --> Delay["Spawn Publisher Threads"]
+ Delay --> Running["Event Loop Running"]
+ Running --> Query["SQL Query Execution"]
+ Query --> Expire["Expiration & Optimization"]
+ Expire --> Shutdown["EventFactory.end()"]
+```
+
+---
+
+## 8. Relationship to Other Modules
+
+| Module | Integration Role |
+|---------|-----------------|
+| Configuration And Packs | Drives scheduled queries and subscriber tuning |
+| SQL Engine And Virtual Tables | Exposes event data as queryable tables |
+| Database Backend | Persists indexed event rows |
+| Logging And Query Metadata | Emits event logs and execution metadata |
+
+The **Events Core And Subscriptions** module acts as the real-time data ingestion and event persistence layer between OS-level monitoring and SQL-based introspection.
+
+---
+
+## 9. Design Characteristics
+
+- Thread-isolated publishers
+- Subscriber-driven storage model
+- Time-indexed database persistence
+- Schedule-aware expiration tuning
+- Plugin-based extensibility
+- Configuration-driven enable/disable logic
+- Safe teardown and deregistration
+
+---
+
+## Conclusion
+
+The **Events Core And Subscriptions** module provides a scalable, extensible event processing framework built around:
+
+- Publisher threads
+- Subscription-based filtering
+- Subscriber-managed persistence
+- SQL-driven retrieval
+
+It enables osquery to transform asynchronous OS signals into consistent, queryable relational data while maintaining performance, safety, and configurability across diverse platforms.
\ No newline at end of file
diff --git a/docs/reference/architecture/extensions-and-ipc/extensions-and-ipc.md b/docs/reference/architecture/extensions-and-ipc/extensions-and-ipc.md
deleted file mode 100644
index b6bf3ce6127..00000000000
--- a/docs/reference/architecture/extensions-and-ipc/extensions-and-ipc.md
+++ /dev/null
@@ -1,375 +0,0 @@
-# Extensions And Ipc
-
-The **Extensions And Ipc** module provides the inter-process communication (IPC) layer and extension framework that allows osquery to be extended at runtime. It enables external processes (extensions) to:
-
-- Register new registry plugins (tables, config plugins, logger plugins, etc.)
-- Execute SQL queries via the core engine
-- Expose custom functionality to the osquery core
-- Communicate securely over platform-specific IPC channels
-
-This module is the foundation for osqueryβs pluggable architecture, separating the core daemon from externally developed functionality while maintaining a controlled and versioned API boundary.
-
----
-
-## 1. Purpose and Design Goals
-
-The Extensions And Ipc module is designed to:
-
-- β
Allow third-party or internal extensions to run as separate processes
-- β
Provide a stable RPC interface using Apache Thrift
-- β
Enforce SDK compatibility and version checks
-- β
Isolate crashes or faults from the core daemon
-- β
Support cross-platform IPC (UNIX domain sockets on POSIX, named pipes on Windows)
-
-At a high level, it implements:
-
-- An **Extension Manager** (running inside osquery core)
-- One or more **Extension Processes** (external binaries)
-- A **Thrift-based RPC layer**
-- Health monitoring and watchdog services
-
----
-
-## 2. High-Level Architecture
-
-The Extensions And Ipc module sits between:
-
-- The **Registry subsystem** (plugin routing)
-- The **SQL engine** (query delegation)
-- The **Dispatcher and runtime threads**
-- External extension processes
-
-### 2.1 CoreβExtension Interaction Model
-
-```mermaid
-flowchart LR
- Core["osquery Core"] -->|"Starts"| Manager["Extension Manager"]
- Manager -->|"Registers routes"| Registry["RegistryFactory"]
-
- ExtensionProc["Extension Process"] -->|"registerExtension()"| Manager
- Manager -->|"Assign UUID"| ExtensionProc
-
- Core -->|"callExtension()"| Manager
- Manager -->|"Route to UUID"| ExtensionProc
-
- ExtensionProc -->|"Response"| Manager
- Manager -->|"PluginResponse"| Core
-```
-
-### 2.2 IPC and Thrift Layer
-
-```mermaid
-flowchart TD
- Client["ExtensionClient"] --> Transport["Thrift Transport"]
- Transport --> Socket["UNIX Socket or Named Pipe"]
- Socket --> Server["ExtensionRunner or ManagerRunner"]
- Server --> Handler["ExtensionHandler or ExtensionManagerHandler"]
- Handler --> Interface["ExtensionInterface / ExtensionManagerInterface"]
- Interface --> Registry["RegistryFactory"]
-```
-
----
-
-## 3. Core Components
-
-### 3.1 Extension Metadata
-
-**Component:** `ExtensionInfo`
-
-Defined in `extensions.h`, this struct mirrors the Thrift `InternalExtensionInfo` type and contains:
-
-- `name`
-- `version`
-- `sdk_version`
-- `min_sdk_version`
-
-This metadata is validated during registration and stored in an `ExtensionList` keyed by a transient `RouteUUID`.
-
----
-
-### 3.2 Extension Manager (Core Side)
-
-**Key Classes:**
-
-- `ExtensionManagerInterface`
-- `ExtensionManagerHandler`
-- `ExtensionManagerRunner`
-- `ExtensionManagerWatcher`
-
-#### Responsibilities
-
-1. Accept extension registrations
-2. Assign unique `RouteUUID` values (via `UuidGenerator`)
-3. Validate SDK compatibility
-4. Maintain active extension metadata
-5. Route plugin calls to registered extensions
-6. Monitor extension health
-
-#### Registration Flow
-
-```mermaid
-sequenceDiagram
- participant Ext as Extension Process
- participant EM as Extension Manager
- participant Reg as RegistryFactory
-
- Ext->>EM: registerExtension(info, registry)
- EM->>EM: Validate name uniqueness
- EM->>EM: Check SDK compatibility
- EM->>Reg: addBroadcast(uuid, registry)
- EM-->>Ext: Return UUID
-```
-
-If duplicate names or incompatible SDK versions are detected, registration fails.
-
----
-
-### 3.3 Extension Process (External Binary)
-
-**Key Classes:**
-
-- `ExtensionRunner`
-- `ExtensionInterface`
-- `ExtensionHandler`
-
-An extension process:
-
-1. Connects to the Extension Manager socket
-2. Registers its broadcasted registry routes
-3. Receives a `RouteUUID`
-4. Starts a Thrift server loop
-5. Waits for calls from the core
-
-Each extension serves the `Extension` Thrift service defined in the generated files.
-
----
-
-### 3.4 Thrift RPC Layer
-
-**Key Files:**
-
-- `impl_thrift.cpp`
-- Generated files under `thrift/gen/`
-
-The module uses Apache Thrift to define two services:
-
-1. `Extension` β implemented by extension processes
-2. `ExtensionManager` β implemented by osquery core
-
-#### Server-Side Wrappers
-
-- `ExtensionHandler` implements `ExtensionIf`
-- `ExtensionManagerHandler` implements `ExtensionManagerIf`
-
-These handlers:
-
-- Translate Thrift structures into internal `PluginRequest`/`PluginResponse`
-- Delegate logic to `ExtensionInterface` or `ExtensionManagerInterface`
-
-#### Client-Side Wrappers
-
-- `ExtensionClient`
-- `ExtensionManagerClient`
-
-They abstract:
-
-- Transport creation
-- Timeout configuration
-- Method invocation
-- Status translation
-
----
-
-### 3.5 Extension API Contracts
-
-The module defines abstract APIs:
-
-- `ExtensionAPI`
-- `ExtensionManagerAPI`
-
-These interfaces enforce a separation between:
-
-- Thrift transport concerns
-- Business logic
-
-This design allows alternative RPC backends in the future while preserving core logic.
-
----
-
-### 3.6 UUID Management
-
-**Component:** `UuidGenerator`
-
-- Generates 16-bit UUID values
-- Tracks active UUIDs in a thread-safe set
-- Removes UUIDs on deregistration
-
-UUIDs uniquely identify extension routes inside `RegistryFactory`.
-
----
-
-### 3.7 External SQL Plugin
-
-**Component:** `ExternalSQLPlugin`
-
-This special plugin allows the core SQL registry to delegate SQL queries to extensions.
-
-```mermaid
-flowchart LR
- SQL["SQL Engine"] --> ExternalSQL["ExternalSQLPlugin"]
- ExternalSQL --> ManagerClient["ExtensionManagerClient"]
- ManagerClient --> Extension["Extension Process"]
-```
-
-Used when tables or query logic are implemented outside the core.
-
----
-
-### 3.8 Watchers and Health Monitoring
-
-**Key Classes:**
-
-- `ExtensionWatcher`
-- `ExtensionManagerWatcher`
-
-#### ExtensionWatcher
-
-- Runs inside extension processes
-- Periodically pings the manager
-- Exits fatally if the manager disappears
-
-#### ExtensionManagerWatcher
-
-- Runs inside core
-- Pings all registered extensions
-- Removes routes if extensions become unreachable
-
-```mermaid
-flowchart TD
- Watcher["ExtensionManagerWatcher"] --> UUIDs["Registered UUIDs"]
- UUIDs --> Ping["Ping Extension"]
- Ping -->|"Success"| Keep["Keep Registered"]
- Ping -->|"Failure x2"| Remove["Remove Broadcast Route"]
-```
-
----
-
-### 3.9 Autoloading and Security
-
-Extensions can be autoloaded using:
-
-- `--extensions_autoload`
-- `--extension` (shell-only)
-
-Security checks include:
-
-- File extension validation (`.ext`, `.exe` on Windows)
-- Directory permission safety checks
-- Ownership validation
-
-Unsafe or improperly permissioned binaries are rejected.
-
----
-
-### 3.10 IPC Channel Integration
-
-On POSIX systems, IPC is primarily UNIX domain sockets. Additionally, worker IPC may use pipe-based channels.
-
-**Component:** `GetChannelType`
-
-This specialization maps a `PipeChannelFactory` to its underlying `PipeChannel` type, integrating extension communication with the worker IPC framework.
-
-This ensures consistent abstraction across:
-
-- Extension IPC
-- Worker-table IPC
-- Internal task communication
-
----
-
-## 4. Lifecycle Overview
-
-### 4.1 Core Startup
-
-```mermaid
-flowchart TD
- Start["Core Start"] --> StartManager["startExtensionManager()"]
- StartManager --> Watcher["ExtensionManagerWatcher"]
- Watcher --> Runner["ExtensionManagerRunner"]
- Runner --> Listen["Thrift Listen"]
-```
-
-### 4.2 Extension Startup
-
-```mermaid
-flowchart TD
- ExtStart["Extension Binary Start"] --> Connect["Connect to Manager Socket"]
- Connect --> Register["registerExtension()"]
- Register --> UUID["Receive UUID"]
- UUID --> StartServer["Start ExtensionRunner"]
- StartServer --> Serve["Serve Thrift Requests"]
-```
-
-### 4.3 Shutdown Flow
-
-- Extension calls `shutdown()` or receives manager failure
-- Manager deregisters UUID
-- `RegistryFactory::removeBroadcast()` is invoked
-- Stale socket paths are cleaned via `removeStalePaths()`
-
----
-
-## 5. Interaction with Other Subsystems
-
-The Extensions And Ipc module interacts with:
-
-- **RegistryFactory** β route registration and broadcast
-- **SQL Engine** β delegated queries
-- **Dispatcher** β background service threads
-- **Flags subsystem** β option propagation
-- **Filesystem utilities** β socket and permission checks
-
-It acts as a boundary layer rather than a business-logic module.
-
----
-
-## 6. Error Handling and Status Model
-
-All RPC responses use:
-
-- `ExtensionStatus`
-- `ExtensionResponse`
-- `ExtensionCode` (SUCCESS, FAILED, FATAL)
-
-This ensures:
-
-- Consistent status propagation across process boundaries
-- Clear failure semantics for SDK mismatches and duplicate registrations
-
----
-
-## 7. Security Considerations
-
-The module enforces:
-
-- SDK version compatibility checks
-- Duplicate extension prevention
-- File permission validation for autoload
-- Socket path isolation per UUID
-- Controlled shutdown behavior
-
-On Windows, named pipes are secured using explicit security descriptors.
-
----
-
-## 8. Summary
-
-The **Extensions And Ipc** module is the runtime extension backbone of osquery. It:
-
-- Implements a bidirectional Thrift RPC system
-- Manages extension lifecycle and UUID assignment
-- Routes registry plugin calls across process boundaries
-- Monitors extension health
-- Enforces compatibility and security constraints
-
-Without this module, osquery would be a static binary. With it, osquery becomes a dynamic, pluggable platform capable of safely integrating externally developed functionality at runtime.
diff --git a/docs/reference/architecture/extensions-framework/extensions-framework.md b/docs/reference/architecture/extensions-framework/extensions-framework.md
new file mode 100644
index 00000000000..2a764738780
--- /dev/null
+++ b/docs/reference/architecture/extensions-framework/extensions-framework.md
@@ -0,0 +1,377 @@
+# Extensions Framework
+
+The **Extensions Framework** enables osquery to be dynamically extended at runtime through external processes. It provides a secure, version-aware, and Thrift-based inter-process communication (IPC) layer that allows third-party or custom components to register new registry plugins, SQL tables, configuration providers, and loggers without modifying the core binary.
+
+At its core, the Extensions Framework:
+
+- Starts and manages an **Extension Manager** inside osquery core
+- Allows external binaries (extensions) to **register registry routes**
+- Provides a **Thrift IPC layer** for RPC-style communication
+- Monitors extension health and lifecycle
+- Enforces SDK compatibility and uniqueness constraints
+
+---
+
+## 1. Architectural Overview
+
+The Extensions Framework is built around a managerβextension model using UNIX domain sockets (or Windows named pipes) and Apache Thrift.
+
+```mermaid
+flowchart TD
+ Core["osquery Core"] --> Manager["Extension Manager"]
+ Manager --> Registry["RegistryFactory"]
+
+ ExtensionA["Extension Process A"] -->|"registerExtension()"| Manager
+ ExtensionB["Extension Process B"] -->|"registerExtension()"| Manager
+
+ Core -->|"callExtension()"| ExtensionA
+ Core -->|"callExtension()"| ExtensionB
+
+ Manager -->|"health checks"| ExtensionA
+ Manager -->|"health checks"| ExtensionB
+```
+
+### Key Roles
+
+- **Extension Manager**: Runs inside osquery core and exposes the Thrift API for extension registration and coordination.
+- **Extension Process**: External binary that registers registry routes and serves plugin calls.
+- **RegistryFactory**: Maintains broadcast routes and resolves plugin calls between core and extensions.
+- **Extension Watchers**: Monitor connectivity and liveness of the manager and registered extensions.
+
+---
+
+## 2. Core Components
+
+### 2.1 ExtensionInfo
+
+**Component:** `osquery.osquery.extensions.extensions.ExtensionInfo`
+
+`ExtensionInfo` encapsulates metadata for each registered extension:
+
+- `name`
+- `version`
+- `sdk_version`
+- `min_sdk_version`
+
+This metadata is validated during registration to:
+
+- Prevent duplicate extension names
+- Enforce minimum SDK compatibility
+- Track active extensions by `RouteUUID`
+
+Internally, extensions are tracked as:
+
+- `ExtensionList = std::map`
+
+---
+
+### 2.2 ExtensionManagerInterface
+
+The `ExtensionManagerInterface` implements the core logic for managing extension lifecycle and registry broadcasts.
+
+Key responsibilities:
+
+- Registering extensions (`registerExtension`)
+- Deregistering extensions (`deregisterExtension`)
+- Tracking metadata (`extensions()`)
+- Enforcing SDK compatibility
+- Exposing osquery flags as `OptionList`
+- Executing SQL on behalf of extensions
+
+```mermaid
+flowchart LR
+ Ext["Extension Process"] -->|"registerExtension"| EM["ExtensionManagerInterface"]
+ EM --> UUID["Assign RouteUUID"]
+ EM --> Registry["RegistryFactory.addBroadcast"]
+ EM --> Store["Store ExtensionInfo"]
+```
+
+During registration:
+
+1. Duplicate extension names are rejected.
+2. SDK compatibility is validated.
+3. A new `RouteUUID` is generated via `UuidGenerator`.
+4. Registry routes are broadcast into `RegistryFactory`.
+5. Metadata is stored for tracking and health monitoring.
+
+---
+
+### 2.3 UuidGenerator
+
+**Component:** `osquery.osquery.extensions.interface.UuidGenerator`
+
+The `UuidGenerator` assigns unique `RouteUUID` values to extensions at registration time.
+
+Characteristics:
+
+- Thread-safe via mutex protection
+- Prevents UUID reuse
+- Ensures uniqueness across active extensions
+- Removes UUID on deregistration
+
+This UUID is:
+
+- Embedded in extension socket paths
+- Used for routing registry calls
+- Used by watchers for health checks
+
+---
+
+### 2.4 Thrift Layer
+
+The Thrift layer provides the RPC mechanism between core and extensions.
+
+Key components:
+
+- `ExtensionManagerHandler`
+- `ExtensionHandler`
+- `ExtensionRunner`
+- `ExtensionManagerRunner`
+- `ImplExtensionClient`
+- `ImplExtensionRunner`
+
+```mermaid
+flowchart TD
+ Client["ExtensionClient"] --> Socket["UNIX Socket / Named Pipe"]
+ Socket --> ThriftServer["TThreadedServer"]
+ ThriftServer --> Handler["ExtensionHandler or ExtensionManagerHandler"]
+ Handler --> Interface["ExtensionInterface Logic"]
+```
+
+### ExtensionManagerHandler
+
+**Component:** `osquery.osquery.extensions.impl_thrift.ExtensionManagerHandler`
+
+Implements Thrift endpoints for:
+
+- `registerExtension`
+- `deregisterExtension`
+- `extensions`
+- `options`
+- `query`
+- `getQueryColumns`
+
+It translates Thrift-generated types into internal osquery structures and delegates to `ExtensionManagerInterface`.
+
+### ImplExtensionClient and ImplExtensionRunner
+
+These provide platform-specific Thrift transport implementations:
+
+- UNIX sockets on Linux/macOS
+- Named pipes on Windows
+- Buffered transport
+- Binary protocol
+- Threaded server model
+
+---
+
+## 3. Lifecycle Management
+
+### 3.1 Starting the Extension Manager
+
+`startExtensionManager()`:
+
+1. Validates socket path availability.
+2. Starts `ExtensionManagerWatcher`.
+3. Starts `ExtensionManagerRunner` (Thrift server).
+4. Optionally enforces required extensions via `extensions_require`.
+
+```mermaid
+flowchart TD
+ Start["startExtensionManager"] --> Check["Check socketExists"]
+ Check --> Watcher["Start ExtensionManagerWatcher"]
+ Watcher --> Runner["Start ExtensionManagerRunner"]
+ Runner --> Ready["Manager Listening"]
+```
+
+---
+
+### 3.2 Starting an Extension
+
+`startExtension()` performs:
+
+1. Wait for manager availability
+2. Broadcast registry routes
+3. Register with manager
+4. Receive assigned `RouteUUID`
+5. Start `ExtensionWatcher`
+6. Start `ExtensionRunner` (Thrift server)
+
+```mermaid
+flowchart TD
+ ExtStart["Extension startExtension"] --> Wait["extensionPathActive"]
+ Wait --> Register["registerExtension"]
+ Register --> UUID["Receive RouteUUID"]
+ UUID --> Watcher["Start ExtensionWatcher"]
+ Watcher --> Runner["Start ExtensionRunner"]
+```
+
+---
+
+### 3.3 Health Monitoring
+
+#### ExtensionWatcher
+
+Monitors:
+
+- Manager socket availability
+- Registration presence
+- Ping response
+
+If the manager disappears and `fatal` is true, the extension exits.
+
+#### ExtensionManagerWatcher
+
+Monitors:
+
+- Each registered extension's socket
+- Repeated ping failures
+- Removes broadcast routes for dead extensions
+
+```mermaid
+flowchart LR
+ ManagerWatcher["ExtensionManagerWatcher"] --> PingExt["Ping Extension"]
+ PingExt -->|"Success"| Healthy["Keep Registered"]
+ PingExt -->|"Failure x2"| Remove["removeBroadcast(uuid)"]
+```
+
+This ensures that:
+
+- Stale registry routes are cleaned up
+- Dead extensions are removed from routing tables
+
+---
+
+## 4. Registry Routing and Plugin Calls
+
+Extensions expose registry routes via broadcast during registration.
+
+When a registry call occurs:
+
+1. `RegistryFactory` resolves the active plugin
+2. If routed to an extension, `callExtension()` is invoked
+3. Thrift client sends request to extension socket
+4. ExtensionHandler translates request and executes locally
+5. Response is returned to core
+
+```mermaid
+flowchart TD
+ CoreCall["RegistryFactory.call"] --> Resolve["Resolve RouteUUID"]
+ Resolve --> IPC["callExtension()"]
+ IPC --> Socket["Thrift RPC"]
+ Socket --> ExtHandler["ExtensionHandler.call"]
+ ExtHandler --> Plugin["Local Plugin Execution"]
+ Plugin --> Response["Return PluginResponse"]
+```
+
+This allows extensions to implement:
+
+- SQL tables
+- Config plugins
+- Logger plugins
+- Distributed plugins
+
+Without linking into the core binary.
+
+---
+
+## 5. SQL Delegation
+
+Extensions do not embed SQLite directly. Instead:
+
+- Complex queries are forwarded to core
+- Column metadata is retrieved via `getQueryColumns`
+- Execution is performed via `ExtensionManagerInterface::query`
+
+The `ExternalSQLPlugin` allows the core to delegate SQL execution to the manager when appropriate.
+
+---
+
+## 6. Option Synchronization
+
+`ExtensionManagerInterface::options()` exports all osquery flags as:
+
+- `OptionList = std::map`
+
+This allows extensions to:
+
+- Discover active config plugin
+- Discover logger plugin
+- Respect runtime configuration
+
+Options are transferred using Thrift-generated structures.
+
+---
+
+## 7. Error and Status Model
+
+The framework uses `ExtensionCode` to standardize status:
+
+- `EXT_SUCCESS`
+- `EXT_FAILED`
+- `EXT_FATAL`
+
+These are mirrored between:
+
+- Internal C++ enums
+- Thrift-generated enums
+
+Each Thrift response includes:
+
+- `code`
+- `message`
+- `uuid`
+
+This ensures consistent cross-process error reporting.
+
+---
+
+## 8. Security Considerations
+
+The Extensions Framework includes several safeguards:
+
+- Safe permission checks for autoloaded extensions
+- SDK version enforcement
+- Duplicate extension name rejection
+- Secure socket handling
+- Windows named pipe ACL enforcement
+- Removal of stale socket paths
+
+Autoloaded extensions must:
+
+- Have safe directory permissions
+- Use allowed binary extensions (e.g., `.ext`, `.exe`)
+
+---
+
+## 9. Relationship to Other Modules
+
+The Extensions Framework integrates with:
+
+- Registry system for plugin routing
+- SQL engine for query delegation
+- Dispatcher for service threading
+- Core runtime for shutdown handling
+- Filesystem utilities for socket management
+
+It acts as the boundary layer between:
+
+- Internal osquery core
+- External extension processes
+
+---
+
+# Summary
+
+The **Extensions Framework** is a robust IPC and lifecycle orchestration layer that enables osquery to be modular and extensible at runtime.
+
+It provides:
+
+- Dynamic plugin injection
+- Secure extension registration
+- Thrift-based RPC communication
+- Health monitoring and cleanup
+- SQL and option delegation
+- Cross-platform transport support
+
+Through this design, osquery maintains a small, stable core while allowing flexible extension through isolated, independently deployable binaries.
\ No newline at end of file
diff --git a/docs/reference/architecture/filesystem-and-fileops-core/filesystem-and-fileops-core.md b/docs/reference/architecture/filesystem-and-fileops-core/filesystem-and-fileops-core.md
new file mode 100644
index 00000000000..6191785e3bd
--- /dev/null
+++ b/docs/reference/architecture/filesystem-and-fileops-core/filesystem-and-fileops-core.md
@@ -0,0 +1,345 @@
+# Filesystem And Fileops Core
+
+## Overview
+
+The **Filesystem And Fileops Core** module provides the cross-platform abstraction layer for file system access, file metadata inspection, permissions handling, and glob-based path resolution within osquery.
+
+It unifies POSIX and Windows behaviors behind a common interface so that higher-level components (SQL tables, extensions, configuration loaders, logging, and distributed features) can interact with files and directories in a platform-agnostic way.
+
+At its heart is the `PlatformFile` abstraction, supported by platform-specific implementations and a set of helper utilities for:
+
+- File open, read, write, seek, and size operations
+- Permission and ownership validation
+- Safe execution and module loading checks
+- Globbing and recursive path resolution
+- Cross-platform `stat`-like metadata retrieval
+- Secure handling of sockets and temporary directories
+
+---
+
+## Architectural Overview
+
+The module is structured around a portable interface with OS-specific backends.
+
+```mermaid
+flowchart TD
+ HighLevel["High-Level Consumers"] --> FilesystemAPI["Filesystem API"]
+ FilesystemAPI --> PlatformFile["PlatformFile"]
+ FilesystemAPI --> GlobEngine["Glob and Pattern Resolver"]
+ FilesystemAPI --> PermissionChecks["Permission and Safety Checks"]
+
+ PlatformFile --> PosixImpl["POSIX Implementation"]
+ PlatformFile --> WindowsImpl["Windows Implementation"]
+
+ GlobEngine --> PosixGlob["POSIX glob()"]
+ GlobEngine --> WindowsGlob["Windows FindFirstFile"]
+
+ PermissionChecks --> PosixPerms["POSIX chmod and stat"]
+ PermissionChecks --> WindowsACL["Windows ACL and SID Logic"]
+```
+
+### Design Principles
+
+1. **Single Logical Interface** β `PlatformFile` and `platform*` helpers hide OS differences.
+2. **Security First** β Explicit safe-permission validation before executing or loading files.
+3. **Non-blocking Support** β Emulated asynchronous semantics across platforms.
+4. **Controlled Resource Usage** β Read limits and block-based file reading.
+5. **Globbing Compatibility** β Approximate POSIX glob behavior on Windows.
+
+---
+
+## Core Components
+
+### 1. AsyncEvent
+
+**Component:** `osquery.osquery.filesystem.fileops.AsyncEvent`
+
+`AsyncEvent` encapsulates Windows asynchronous I/O state. It is used to simulate POSIX-style non-blocking file semantics on Windows using the overlapped I/O API.
+
+Responsibilities:
+
+- Maintain `OVERLAPPED` structure
+- Track active asynchronous reads
+- Manage temporary buffers
+- Detect incomplete I/O operations
+
+On POSIX systems, non-blocking behavior relies on `O_NONBLOCK` and `EAGAIN`.
+
+---
+
+### 2. PlatformTime
+
+**Component:** `osquery.osquery.filesystem.fileops.PlatformTime`
+
+`PlatformTime` abstracts access and modification timestamps across platforms:
+
+- POSIX: `timeval`
+- Windows: `FILETIME`
+
+Used by `PlatformFile::getFileTimes()` to normalize time retrieval.
+
+---
+
+### 3. stat Implementations
+
+Components:
+
+- `osquery.osquery.filesystem.fileops.stat`
+- `osquery.osquery.filesystem.filesystem.stat`
+- `osquery.osquery.filesystem.posix.fileops.stat`
+
+The module provides layered metadata access:
+
+- POSIX: `lstat`, `fstat`, `struct stat`
+- Windows: `platformStat` populating `WINDOWS_STAT`
+
+Windows-specific metadata includes:
+
+- File ID and inode mapping
+- SID-based UID/GID translation
+- NTFS attributes
+- Version information
+- Original filename from version resource
+
+This allows higher-level SQL tables (e.g., file tables) to present consistent schemas.
+
+---
+
+### 4. WindowsFindFiles
+
+**Component:** `osquery.osquery.filesystem.windows.fileops.WindowsFindFiles`
+
+Encapsulates `FindFirstFileW` and `FindNextFileW` logic to enumerate directory contents.
+
+Used internally by the Windows glob implementation to:
+
+- Enumerate matching directories
+- Apply brace and wildcard expansions
+- Normalize returned paths
+
+---
+
+## PlatformFile Abstraction
+
+`PlatformFile` is the central class for file I/O.
+
+### Responsibilities
+
+- Open files using portable mode flags
+- Support read, write, seek, and size operations
+- Detect special files
+- Track pending non-blocking operations
+- Validate ownership and permissions
+- Provide access to native file handles
+
+### Mode Abstraction
+
+Portable flags are defined to emulate cross-platform open modes:
+
+- `PF_READ`
+- `PF_WRITE`
+- `PF_CREATE_NEW`
+- `PF_OPEN_EXISTING`
+- `PF_NONBLOCK`
+- `PF_APPEND`
+
+These are translated internally into:
+
+- POSIX: `open()` flags (`O_RDONLY`, `O_CREAT`, etc.)
+- Windows: `CreateFileW()` access masks and disposition flags
+
+### Lifecycle
+
+```mermaid
+flowchart TD
+ Create["Create PlatformFile"] --> Open["Open Native Handle"]
+ Open --> Valid{"Valid Handle?"}
+ Valid -->|Yes| Operate["Read or Write or Seek"]
+ Valid -->|No| Error["Return Failure"]
+ Operate --> Close["Destructor Closes Handle"]
+```
+
+---
+
+## File Reading and Writing
+
+### Controlled Reads
+
+`readFile()` enforces a configurable maximum read size.
+
+Key behaviors:
+
+- Uses non-blocking mode when supported
+- Reads in blocks when file size unknown
+- Aborts if size exceeds configured limit
+- Supports streaming via predicate callback
+
+This prevents excessive memory usage and improves resilience.
+
+### Writing
+
+`writeTextFile()`:
+
+- Opens file with requested permissions
+- Applies `platformChmod()` to enforce mode
+- Writes full content
+- Verifies byte counts
+
+---
+
+## Globbing and Path Resolution
+
+The module implements a portable glob engine.
+
+### POSIX
+
+- Uses native `glob()`
+- Supports `GLOB_TILDE`, `GLOB_MARK`, `GLOB_BRACE`
+
+### Windows
+
+- Converts glob to regex when needed
+- Uses `FindFirstFileW`
+- Implements brace expansion heuristics
+- Emulates tilde expansion via `USERPROFILE`
+
+### Recursive Globs
+
+Double-star patterns (`**`) are expanded iteratively with loop detection.
+
+```mermaid
+flowchart TD
+ Pattern["Input Pattern"] --> Normalize["Canonicalize Base Path"]
+ Normalize --> Expand["Apply Wildcards"]
+ Expand --> DetectLoop{"Symlink Loop?"}
+ DetectLoop -->|Yes| Stop["Stop Recursion"]
+ DetectLoop -->|No| Recurse["Continue Expansion"]
+ Recurse --> Filter["Apply Folder or File Filter"]
+```
+
+---
+
+## Permission and Safety Model
+
+Security-sensitive logic ensures that executables and modules are safe to load.
+
+### Ownership Checks
+
+- `isOwnerRoot()`
+- `isOwnerCurrentUser()`
+
+On Windows, this maps to SID comparisons for:
+
+- Administrators
+- Local System
+
+### Executable and Safe Permissions
+
+`hasSafePermissions()` verifies:
+
+- No unsafe write permissions
+- Parent directory is protected
+- File not world-writable
+
+On Windows, this involves:
+
+- Parsing DACLs
+- Detecting allow-write ACEs
+- Ensuring deny precedence where required
+
+### Safe Database Permissions
+
+`platformSetSafeDbPerms()` enforces restricted access:
+
+- POSIX: `0700`
+- Windows: Full control to SYSTEM and Administrators only
+
+---
+
+## Directory and Path Utilities
+
+The module provides portable utilities for:
+
+- `pathExists()`
+- `isDirectory()`
+- `createDirectory()`
+- `removePath()`
+- `movePath()`
+- `platformAccess()`
+- `platformIsTmpDir()`
+- `platformIsFileAccessible()`
+
+These functions abstract:
+
+- `boost::filesystem`
+- POSIX `stat()` and `access()`
+- Windows ACL-based access checks
+
+---
+
+## Socket Handling
+
+`socketExists()` abstracts UNIX domain sockets and Windows named pipes.
+
+Behavior differs:
+
+- POSIX: filesystem path existence + writability
+- Windows: `WaitNamedPipeW()` with timeout
+
+This is critical for extension manager communication.
+
+---
+
+## Home and System Directory Resolution
+
+`getHomeDirectory()` and `getSystemRoot()` normalize:
+
+- POSIX: `$HOME`, `/`
+- Windows: `USERPROFILE`, Windows directory
+
+`osqueryHomeDirectory()` ensures a writable `.osquery` directory or falls back to a temporary directory.
+
+---
+
+## Cross-Platform I/O Flow
+
+```mermaid
+flowchart TD
+ Caller["Caller"] --> PF["PlatformFile"]
+ PF --> OSCheck{"Operating System"}
+ OSCheck -->|POSIX| POSIXIO["open read write lseek"]
+ OSCheck -->|Windows| WINIO["CreateFile ReadFile WriteFile"]
+ POSIXIO --> Result["Normalized Result"]
+ WINIO --> Result
+```
+
+---
+
+## Integration Within osquery
+
+Filesystem And Fileops Core underpins:
+
+- SQL virtual tables accessing files
+- Configuration loaders reading JSON and packs
+- Logging output targets
+- Extension manager sockets
+- Distributed query artifact access
+- Safe executable and module loading
+
+By isolating OS-specific complexity in this module, the rest of the system can rely on consistent file semantics and robust security checks.
+
+---
+
+## Summary
+
+The **Filesystem And Fileops Core** module is the portability and safety backbone of osqueryβs file interaction layer.
+
+It provides:
+
+- Unified file I/O abstraction
+- Cross-platform metadata retrieval
+- Robust permission validation
+- Secure globbing and path expansion
+- Defensive read limits and safe directory checks
+
+Through careful emulation of POSIX semantics on Windows and strict permission enforcement, it ensures reliable and secure file operations across supported operating systems.
diff --git a/docs/reference/architecture/filesystem-and-path-utilities/filesystem-and-path-utilities.md b/docs/reference/architecture/filesystem-and-path-utilities/filesystem-and-path-utilities.md
deleted file mode 100644
index 579007ad3ba..00000000000
--- a/docs/reference/architecture/filesystem-and-path-utilities/filesystem-and-path-utilities.md
+++ /dev/null
@@ -1,338 +0,0 @@
-# Filesystem And Path Utilities
-
-## Overview
-
-The **Filesystem And Path Utilities** module provides a cross-platform abstraction layer for file operations, path handling, globbing, permissions, and filesystem metadata inspection across Linux, macOS (POSIX), and Windows systems.
-
-It is a foundational module used by higher-level components to:
-
-- Read and write files safely
-- Enforce secure permission models
-- Resolve glob patterns
-- Inspect file metadata
-- Enumerate directories and mounts
-- Interact with `/proc` on Linux
-- Provide consistent APIs across POSIX and Windows
-
-This module hides operating system differences while preserving security guarantees and performance characteristics.
-
----
-
-## Architectural Overview
-
-```mermaid
-flowchart TD
- Caller["Core / SQL / Extensions"] --> FSAPI["Filesystem API"]
-
- subgraph abstraction_layer["Cross-Platform Abstraction"]
- FSAPI --> PlatformFile["PlatformFile"]
- FSAPI --> Glob["platformGlob()"]
- FSAPI --> Perms["platformChmod()"]
- FSAPI --> Access["platformAccess()"]
- FSAPI --> Stat["platformStat() / lstat()"]
- end
-
- subgraph posix_layer["POSIX Implementation"]
- PlatformFile --> POSIXFile["open/read/write/lstat"]
- Glob --> POSIXGlob["glob()"]
- end
-
- subgraph windows_layer["Windows Implementation"]
- PlatformFile --> WinFile["CreateFile / ReadFile"]
- Glob --> WinGlob["FindFirstFileW"]
- Perms --> WinACL["ACL Manipulation"]
- end
-```
-
-The abstraction layer ensures that callers use a unified API regardless of the underlying OS.
-
----
-
-## Core Components
-
-### 1. PlatformFile
-
-**Component:** `osquery.osquery.filesystem.fileops.PlatformFile`
-
-`PlatformFile` is the central abstraction for file I/O.
-
-It provides:
-
-- Cross-platform file opening modes (`PF_READ`, `PF_WRITE`, etc.)
-- Non-blocking I/O support
-- Ownership validation
-- Executable checks
-- Safe permission verification
-- Seek and size inspection
-- File time retrieval
-
-### Lifecycle Model
-
-```mermaid
-flowchart TD
- Open["Open PlatformFile"] --> Validate["Handle Valid?"]
- Validate -->|No| Fail["Return Error"]
- Validate -->|Yes| IO["Read / Write / Seek"]
- IO --> Close["Destructor Closes Handle"]
-```
-
-Platform-specific implementations exist for:
-
-- POSIX (`open`, `read`, `write`, `fstat`)
-- Windows (`CreateFileW`, `ReadFile`, overlapped I/O)
-
----
-
-### 2. File Metadata and Stat Structures
-
-#### POSIX
-- `osquery.osquery.filesystem.posix.fileops.stat`
-
-Uses:
-- `stat`
-- `lstat`
-- `fstat`
-
-#### Windows
-- `osquery.osquery.filesystem.fileops.WINDOWS_STAT`
-- `osquery.osquery.filesystem.fileops.win_stat`
-- `osquery.osquery.filesystem.windows.fileops.WindowsFindFiles`
-
-Windows provides:
-- File ID
-- Volume serial
-- ACL-derived ownership
-- File version metadata
-- Attributes (hidden, system, archive)
-
-```mermaid
-flowchart LR
- Path["File Path"] --> StatCall["platformStat()"]
- StatCall -->|POSIX| POSIXStat["struct stat"]
- StatCall -->|Windows| WinStat["WINDOWS_STAT"]
-```
-
----
-
-### 3. Globbing and Pattern Resolution
-
-**Core APIs:**
-- `platformGlob()`
-- `resolveFilePattern()`
-- `replaceGlobWildcards()`
-
-Supports:
-- `*` and `?`
-- `**` recursive globs
-- `%` SQL-style wildcard translation
-- Brace expansion (Windows regex translation)
-
-Recursive globbing includes loop detection using inode tracking.
-
-```mermaid
-flowchart TD
- Pattern["Input Pattern"] --> Normalize["replaceGlobWildcards()"]
- Normalize --> Expand["platformGlob()"]
- Expand --> Filter["Apply GLOB_FILES / GLOB_FOLDERS"]
- Filter --> Results["Resolved Paths"]
-```
-
----
-
-### 4. Permissions and Security Enforcement
-
-Security is a major responsibility of this module.
-
-#### Ownership Checks
-- `isOwnerRoot()`
-- `isOwnerCurrentUser()`
-
-#### Safe Permission Enforcement
-- `hasSafePermissions()`
-- `platformSetSafeDbPerms()`
-
-On Windows, safe permissions require:
-- Only Administrators and SYSTEM have write privileges
-- Explicit ACL validation
-
-On POSIX, safety approximates:
-- Mode `0700` for sensitive files
-- No world-writable flags
-
-#### Execution Safety
-
-The `safePermissions()` helper ensures:
-
-- File exists
-- Not located in temporary directory
-- Proper ownership
-- Proper executable bits
-
-This protects extension loading and module execution paths.
-
----
-
-### 5. File Reading and Writing Utilities
-
-High-level helpers include:
-
-- `readFile()` (streaming and full-buffer versions)
-- `writeTextFile()`
-- `isReadable()`
-- `isWritable()`
-- `pathExists()`
-- `removePath()`
-- `movePath()`
-
-A configurable limit (`read_max`) prevents excessive file reads.
-
-```mermaid
-flowchart TD
- ReadCall["readFile()"] --> Open["PlatformFile"]
- Open --> SizeCheck["checkFileReadLimit()"]
- SizeCheck --> Loop["Block Read Loop"]
- Loop --> Predicate["Callback / Buffer"]
-```
-
----
-
-### 6. Home Directory and System Paths
-
-Cross-platform resolution of:
-
-- Current user home directory (`getHomeDirectory()`)
-- Osquery working directory (`osqueryHomeDirectory()`)
-- System root (`getSystemRoot()`)
-
-Fallback behavior:
-
-- Uses environment variables first
-- Falls back to system APIs
-- Falls back to temp directory if needed
-
----
-
-## Linux-Specific Extensions
-
-### Mounted Filesystems
-
-**Component:** `osquery.osquery.filesystem.linux.mounts.MountInformation`
-
-Provides structured information for mounted filesystems:
-
-- Device path
-- Filesystem type
-- Mount flags
-- `statfs` block and inode counts
-
-```mermaid
-flowchart LR
- getMounted["getMountedFilesystems()"] --> MountInfo["MountInformation"]
- MountInfo --> StatFS["StatFsInfo"]
-```
-
----
-
-### /proc Parsing and Socket Inspection
-
-**Components:**
-- `osquery.osquery.filesystem.linux.proc.SocketInfo`
-- `osquery.osquery.filesystem.linux.proc.SocketProcessInfo`
-
-Capabilities:
-
-- Enumerate processes via `/proc`
-- Map socket inode to process
-- Decode hex-encoded network addresses
-- Parse `/proc/net/*` files
-
-```mermaid
-flowchart TD
- Proc["/proc"] --> Enumerate["procEnumerateProcesses()"]
- Enumerate --> FDEnum["procEnumerateProcessDescriptors()"]
- FDEnum --> SocketMap["SocketInodeToProcessInfoMap"]
-```
-
-This enables socket tables and network observability features.
-
----
-
-## Windows-Specific Enhancements
-
-Windows includes additional capabilities:
-
-- NTFS ACL manipulation
-- File version extraction
-- Original filename extraction from PE metadata
-- Overlapped (async) I/O (`AsyncEvent`)
-- Named pipe detection (`socketExists()`)
-
-Windows globbing is implemented using:
-- `FindFirstFileW`
-- Regex translation for brace patterns
-
----
-
-## Security Model Summary
-
-```mermaid
-flowchart TD
- File["Candidate File"] --> Exists["Exists?"]
- Exists -->|No| Reject["Reject"]
- Exists --> Owner["Owner Root or Current User?"]
- Owner -->|No| Reject
- Owner --> Writable["World Writable?"]
- Writable -->|Yes| Reject
- Writable --> Exec["Executable Required?"]
- Exec --> Accept["Safe"]
-```
-
-This ensures:
-
-- No unsafe extension loading
-- No world-writable execution
-- No loading from temp directories
-
----
-
-## Integration Within the System
-
-The Filesystem And Path Utilities module is used by:
-
-- SQL virtual tables for file metadata
-- Configuration loading
-- Extension management
-- Logging subsystems
-- Distributed query execution
-- Event subscribers
-
-It acts as a **trusted boundary layer** between:
-
-- User-supplied file paths
-- The operating system
-- Internal execution logic
-
----
-
-## Key Design Principles
-
-1. **Cross-platform consistency**
-2. **Security-first permission enforcement**
-3. **Non-blocking support where possible**
-4. **Recursive glob loop detection**
-5. **Minimal exposure of OS-specific details**
-
----
-
-## Conclusion
-
-The **Filesystem And Path Utilities** module is a foundational cross-platform subsystem responsible for:
-
-- File I/O abstraction
-- Secure permission validation
-- Glob resolution
-- Filesystem metadata access
-- Linux `/proc` inspection
-- Windows ACL and metadata handling
-
-It enables higher-level components to operate safely and consistently across heterogeneous operating systems while enforcing strict security guarantees.
\ No newline at end of file
diff --git a/docs/reference/architecture/logging-and-query-metadata/logging-and-query-metadata.md b/docs/reference/architecture/logging-and-query-metadata/logging-and-query-metadata.md
new file mode 100644
index 00000000000..c8d899e9bee
--- /dev/null
+++ b/docs/reference/architecture/logging-and-query-metadata/logging-and-query-metadata.md
@@ -0,0 +1,314 @@
+# Logging And Query Metadata
+
+## Overview
+
+The **Logging And Query Metadata** module is responsible for transforming query executions and internal runtime events into structured, serializable, and transportable log artifacts.
+
+It acts as the bridge between:
+
+- The SQL execution engine and scheduler
+- The persistent query state stored in the database backend
+- The pluggable logging framework
+- External logging and distributed systems
+
+This module defines:
+
+- Query result representation (`QueryLogItem`)
+- Differential result computation (`DiffResults`)
+- Scheduled query metadata (`ScheduledQuery`)
+- Query execution performance metrics (`QueryPerformance`)
+- Logger plugin contracts and status log lines (`StatusLogLine`)
+
+It does **not** execute SQL directly (see the SQL Engine And Virtual Tables module) and does **not** manage persistent storage directly (see the Database Backend module). Instead, it orchestrates how results and metadata are formatted, diffed, tracked, and emitted.
+
+---
+
+## Architectural Positioning
+
+```mermaid
+flowchart TD
+ Scheduler["Configuration And Packs"] -->|"creates"| ScheduledQuery
+ ScheduledQuery -->|"executes"| SQLEngine["SQL Engine And Virtual Tables"]
+ SQLEngine -->|"returns rows"| QueryLayer["Query"]
+ QueryLayer -->|"computes diff"| DiffResultsNode["DiffResults"]
+ QueryLayer -->|"builds"| QueryLogItemNode["QueryLogItem"]
+ QueryLogItemNode -->|"serialize"| LoggerPluginNode["LoggerPlugin"]
+ LoggerPluginNode -->|"emits"| ExternalSystem["External Logging System"]
+ QueryLayer -->|"store previous"| DatabaseBackend["Database Backend"]
+```
+
+### Key Relationships
+
+- **Configuration And Packs** defines scheduled queries.
+- **SQL Engine And Virtual Tables** executes SQL and produces row sets.
+- **Database Backend** persists historical results.
+- **Logging And Query Metadata**:
+ - Computes diffs between executions
+ - Tracks metadata (epoch, counter, timestamps)
+ - Serializes results
+ - Sends structured logs to logger plugins
+
+---
+
+## Core Responsibilities
+
+### 1. Scheduled Query Metadata
+
+**Component:** `ScheduledQuery`
+
+Represents the runtime metadata of a scheduled query:
+
+- Query name and SQL
+- Pack name
+- Execution interval and startup priority
+- Denylisting state
+- Query options (`snapshot`, `removed`, etc.)
+
+Key behaviors:
+
+- `isSnapshotQuery()` determines if the query emits full results every run.
+- `reportRemovedRows()` determines whether removed rows are included in logs.
+
+This metadata drives how results are processed and serialized downstream.
+
+---
+
+### 2. Historical State and Diffing
+
+**Components:**
+
+- `Query`
+- `DiffResults`
+
+The `Query` class is the stateful interface between execution results and the persistent database.
+
+#### Lifecycle of a Scheduled Query Execution
+
+```mermaid
+flowchart TD
+ Start["Scheduled Query Execution"] --> FetchOld["getPreviousQueryResults()"]
+ FetchOld --> Exec["Execute SQL"]
+ Exec --> Diff["diff(old, new)"]
+ Diff --> Store["saveQueryResults()"]
+ Store --> BuildLog["Construct QueryLogItem"]
+ BuildLog --> End["Emit Log"]
+```
+
+### `DiffResults`
+
+Encapsulates the difference between:
+
+- Previous result set
+- Current result set
+
+Structure:
+
+- `added`: newly observed rows
+- `removed`: rows no longer present
+
+Utility:
+
+- `hasNoResults()` avoids emitting empty logs.
+- Serialization helpers convert diffs into JSON.
+
+The diff mechanism ensures efficient logging by emitting only state transitions instead of full snapshots (unless configured otherwise).
+
+---
+
+### 3. Query Log Representation
+
+**Component:** `QueryLogItem`
+
+`QueryLogItem` is the canonical log artifact emitted by the system.
+
+It contains:
+
+- `isSnapshot`: snapshot vs differential mode
+- `results`: differential results (`DiffResults`)
+- `snapshot_results`: full result set
+- `name`: scheduled query name
+- `identifier`: host identity
+- `time` and `calendar_time`
+- `epoch`: logical configuration version
+- `counter`: execution counter
+- `decorations`: additional metadata fields
+
+#### Serialization Paths
+
+The module provides multiple serialization formats:
+
+- `serializeQueryLogItem()` β JSON document
+- `serializeQueryLogItemJSON()` β JSON string
+- `serializeQueryLogItemAsEvents()` β event-based representation
+- `serializeQueryLogItemAsEventsJSON()` β event list JSON strings
+
+This flexibility enables:
+
+- Batch logging
+- Event-driven logging
+- Snapshot logging
+- Differential logging
+
+---
+
+### 4. Query Performance Tracking
+
+**Component:** `QueryPerformance`
+
+Tracks runtime characteristics of each query:
+
+- Execution count
+- Wall time (seconds and milliseconds)
+- User and system CPU time
+- Memory consumption
+- Output size
+
+It supports:
+
+- CSV serialization (`toCSV()`)
+- CSV deserialization constructor
+
+Performance metrics are essential for:
+
+- Detecting expensive queries
+- Observability dashboards
+- Adaptive scheduling logic
+- Operational debugging
+
+---
+
+### 5. Logging Plugin Interface
+
+**Components:**
+
+- `StatusLogLine`
+- `LoggerPlugin`
+
+This module defines the contract between internal logging and pluggable logging backends.
+
+#### `StatusLogLine`
+
+Represents structured status logs:
+
+- Severity (`O_INFO`, `O_WARNING`, `O_ERROR`, `O_FATAL`)
+- Filename and line number
+- Message
+- Timestamps (UNIX and calendar)
+- Host identifier
+
+These are buffered during early startup and delivered to the logger during initialization.
+
+---
+
+### `LoggerPlugin`
+
+A pluggable interface allowing integration with:
+
+- Syslog
+- Splunk
+- Kafka pipelines
+- Cloud logging systems
+
+Core extension points:
+
+- `logString()` (mandatory)
+- `logStatus()` (optional)
+- `logSnapshot()` (optional)
+- `logEvent()` (optional)
+- `logStringBatch()` (batch event handling)
+
+Feature negotiation:
+
+```mermaid
+flowchart LR
+ Logger["LoggerPlugin"] -->|"usesLogStatus()"| StatusHandling["Handle Glog Status"]
+ Logger -->|"usesLogEvent()"| EventHandling["Handle Event Forwarding"]
+ Logger -->|"logSnapshot()"| SnapshotHandling["Snapshot Optimization"]
+```
+
+The logger can opt into:
+
+- Handling Glog statuses directly
+- Receiving individual events
+- Receiving batched events
+- Handling large snapshot payloads separately
+
+This decouples core execution from output transport.
+
+---
+
+## End-to-End Data Flow
+
+```mermaid
+flowchart TD
+ Config["Configuration And Packs"] --> SchedulerExec["Scheduled Query"]
+ SchedulerExec --> SQLEngine["SQL Engine"]
+ SQLEngine --> QueryState["Query"]
+ QueryState --> DiffLayer["DiffResults"]
+ QueryState --> Perf["QueryPerformance"]
+ DiffLayer --> LogItem["QueryLogItem"]
+ Perf --> LogItem
+ LogItem --> Serializer["JSON Serialization"]
+ Serializer --> Logger["LoggerPlugin"]
+ Logger --> Sink["External Sink"]
+ QueryState --> Database["Database Backend"]
+```
+
+---
+
+## Interaction With Other Modules
+
+This module collaborates closely with:
+
+- **Configuration And Packs** (scheduled query definitions)
+- **SQL Engine And Virtual Tables** (query execution)
+- **Database Backend** (persistent historical state)
+- **Distributed Querying** (remote execution results)
+- **Extensions Framework** (custom logger plugins)
+
+It intentionally does not:
+
+- Parse SQL
+- Implement storage engines
+- Perform network transport directly
+
+Instead, it standardizes metadata and logging semantics.
+
+---
+
+## Design Principles
+
+### 1. Differential Logging First
+Default behavior minimizes output volume by logging only changes.
+
+### 2. Snapshot Flexibility
+Queries can explicitly request snapshot semantics.
+
+### 3. Pluggable Logging
+Logging transport is fully decoupled via plugin interfaces.
+
+### 4. Persistent State Awareness
+Every scheduled query execution is contextualized by:
+
+- Epoch (configuration version)
+- Counter (execution count)
+- Previous result set
+
+### 5. Observability Built-In
+Performance metrics are tracked alongside result data.
+
+---
+
+## Summary
+
+The **Logging And Query Metadata** module is the structured observability layer of the system.
+
+It:
+
+- Tracks query execution metadata
+- Computes result deltas
+- Serializes structured logs
+- Maintains historical state
+- Exposes extensible logging interfaces
+
+By separating execution, storage, and transport concerns, it enables scalable, efficient, and flexible logging architectures while preserving rich metadata for auditing, debugging, and analytics.
\ No newline at end of file
diff --git a/docs/reference/architecture/logging-and-query-observability/logging-and-query-observability.md b/docs/reference/architecture/logging-and-query-observability/logging-and-query-observability.md
deleted file mode 100644
index cf98d585c16..00000000000
--- a/docs/reference/architecture/logging-and-query-observability/logging-and-query-observability.md
+++ /dev/null
@@ -1,409 +0,0 @@
-# Logging And Query Observability
-
-## Overview
-
-The **Logging And Query Observability** module is responsible for transforming raw query executions and internal status events into structured, serialized, and transport-ready log artifacts.
-
-It sits at the intersection of:
-
-- The **SQL execution layer** (see [SQL Engine And Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md))
-- The **persistent state layer** (see [Database And Storage Plugins](../database-and-storage-plugins/database-and-storage-plugins.md))
-- The **configuration and scheduling layer** (see [Configuration And Packs](../configuration-and-packs/configuration-and-packs.md))
-- The **pluggable logging infrastructure**
-
-This module provides:
-
-- Query result diffing and snapshot handling
-- Query execution metadata and performance tracking
-- Structured log serialization (JSON, event-based)
-- Pluggable logger interface for external sinks (TLS, filesystem, syslog, etc.)
-- Status log forwarding and event streaming support
-
----
-
-## Architectural Position
-
-```mermaid
-flowchart TD
- Config["Configuration And Packs"] --> Scheduler["Scheduled Query"]
- Scheduler --> SQ["ScheduledQuery Struct"]
- SQ --> QueryObj["Query State Manager"]
- QueryObj --> DB["Database And Storage Plugins"]
-
- QueryObj --> Diff["DiffResults Engine"]
- Diff --> LogItem["QueryLogItem"]
- LogItem --> Serializer["JSON Serialization"]
- Serializer --> Logger["LoggerPlugin"]
-
- StatusLogs["Internal Status Events"] --> StatusLine["StatusLogLine"]
- StatusLine --> Logger
-
- Logger --> External["External Logging Backend"]
-```
-
-The Logging And Query Observability module acts as a transformation and routing layer:
-
-1. Queries execute.
-2. Results are compared with historical state.
-3. Changes are wrapped in structured log items.
-4. Logs are serialized.
-5. A `LoggerPlugin` implementation forwards them upstream.
-
----
-
-## Core Components
-
-This module consists of five primary building blocks:
-
-- **LoggerPlugin** and **StatusLogLine** β Pluggable logging interface
-- **QueryLogItem** β Structured representation of query output
-- **DiffResults** β Result set comparison engine
-- **QueryPerformance** β Execution metrics and telemetry
-- **ScheduledQuery** β Query scheduling metadata model
-
-Each component addresses a specific concern in the observability pipeline.
-
----
-
-## LoggerPlugin And StatusLogLine
-
-### Purpose
-
-The logging subsystem provides a pluggable abstraction for forwarding:
-
-- Query results
-- Snapshot outputs
-- Event batches
-- Internal status logs
-
-### StatusLogLine
-
-`StatusLogLine` represents a single internal status entry emitted by the runtime. It includes:
-
-- Severity (`O_INFO`, `O_WARNING`, `O_ERROR`, `O_FATAL`)
-- Source file and line number
-- Human-readable message
-- UNIX timestamp and calendar time
-- Host identifier
-
-This structure decouples internal logging (e.g., Glog) from external log sinks.
-
-### LoggerPlugin
-
-`LoggerPlugin` is an abstract plugin interface that allows custom logging backends.
-
-Key extensibility points:
-
-- `logString` (required) β Primary logging entrypoint
-- `logStatus` β Handles structured status logs
-- `logSnapshot` β Special handling for large snapshot queries
-- `logEvent` / `logStringBatch` β Direct event forwarding
-- `usesLogStatus` β Opt-in takeover of internal status handling
-- `usesLogEvent` β Opt-in direct event streaming
-
-### Logger Feature Flags
-
-Logger plugins can advertise support for:
-
-- `LOGGER_FEATURE_LOGSTATUS`
-- `LOGGER_FEATURE_LOGEVENT`
-
-This enables selective routing decisions at runtime.
-
-### Logger Lifecycle
-
-```mermaid
-flowchart TD
- Init["System Initialization"] --> Buffer["Buffer Early Status Logs"]
- Buffer --> LoadConfig["Load Configuration"]
- LoadConfig --> Discover["Discover Logger Plugin"]
- Discover --> InitLogger["LoggerPlugin.init()"]
- InitLogger --> Flush["Flush Buffered StatusLogLine Entries"]
- Flush --> Runtime["Runtime Logging"]
-```
-
-Before the logger initializes, early status logs are buffered and later flushed during `init()`.
-
-This ensures no observability gaps during startup.
-
----
-
-## ScheduledQuery
-
-`ScheduledQuery` models the runtime attributes of a scheduled query.
-
-Key attributes:
-
-- `pack_name` β Configuration pack source
-- `name` β Unique identifier
-- `query` β SQL statement
-- `interval` β Execution frequency
-- `startup_priority` β Startup execution control
-- `denylisted` β Configuration-level suppression
-- `options` β Behavioral flags (e.g., snapshot, removed)
-
-### Behavioral Flags
-
-- `snapshot` β Always log full results
-- `removed` β Control reporting of removed rows
-
-This structure originates from configuration parsing (see [Configuration And Packs](../configuration-and-packs/configuration-and-packs.md)) and feeds directly into execution and logging logic.
-
----
-
-## Query State Management
-
-### Query
-
-The `Query` class maintains persistent state for a scheduled query.
-
-Responsibilities:
-
-- Retrieve previous results from storage
-- Compute diffs between executions
-- Track query epoch
-- Maintain execution counter
-- Persist updated result sets
-
-It interacts with the database abstraction (see [Database And Storage Plugins](../database-and-storage-plugins/database-and-storage-plugins.md)).
-
-### Differential Execution Model
-
-```mermaid
-flowchart LR
- Old["Previous Results"] --> DiffEngine["diff()"]
- New["Current Results"] --> DiffEngine
- DiffEngine --> Added["Added Rows"]
- DiffEngine --> Removed["Removed Rows"]
-```
-
-The `addNewResults` method:
-
-1. Loads historical state.
-2. Computes a `DiffResults` structure.
-3. Updates persistent storage.
-4. Returns differential output for logging.
-
-This avoids repeatedly logging identical datasets and reduces log volume.
-
----
-
-## DiffResults
-
-`DiffResults` represents the delta between two query executions.
-
-Structure:
-
-- `added` β Rows present in new results but not old
-- `removed` β Rows present in old results but not new
-
-### Properties
-
-- Move-only semantics (efficient handling of large result sets)
-- Equality comparison support
-- JSON serialization helpers
-
-### Serialization Flow
-
-```mermaid
-flowchart TD
- Diff["DiffResults"] --> Serialize["serializeDiffResults()"]
- Serialize --> JSONDoc["JSON Document"]
- JSONDoc --> Logger["LoggerPlugin"]
-```
-
-Diff serialization ensures:
-
-- Stable output format
-- Optional numeric preservation
-- Compatibility with downstream analytics pipelines
-
----
-
-## QueryLogItem
-
-`QueryLogItem` is the canonical structured representation of a query execution.
-
-It includes:
-
-- `isSnapshot` β Snapshot vs differential indicator
-- `results` β `DiffResults`
-- `snapshot_results` β Full results (if snapshot)
-- `name` β Query name
-- `identifier` β Host ID
-- `time` / `calendar_time`
-- `epoch`
-- `counter`
-- `decorations` β Arbitrary metadata
-
-### Equality Semantics
-
-Two `QueryLogItem` instances are equal if:
-
-- Their `DiffResults` match
-- Their query names match
-
-This enables deduplication logic in higher-level processing.
-
-### Serialization Variants
-
-The module supports multiple output formats:
-
-1. Structured JSON object
-2. JSON string
-3. Event-style records (split per action)
-
-```mermaid
-flowchart TD
- Item["QueryLogItem"] --> JSON1["serializeQueryLogItem()"]
- Item --> JSON2["serializeQueryLogItemJSON()"]
- Item --> Events1["serializeQueryLogItemAsEvents()"]
- Item --> Events2["serializeQueryLogItemAsEventsJSON()"]
-```
-
-Event-based serialization allows each row addition/removal to be emitted as an individual log record.
-
----
-
-## QueryPerformance
-
-`QueryPerformance` provides execution telemetry.
-
-Metrics tracked:
-
-- Total executions
-- Last execution time
-- Wall time (total and last)
-- User/system CPU time
-- Memory usage
-- Output size
-
-### CSV Serialization
-
-Performance data is stored and transferred using a CSV representation:
-
-- Constructor accepts CSV
-- `toCSV()` exports current state
-
-This lightweight format reduces overhead in persistent storage.
-
-### Observability Use Cases
-
-- Detect slow queries
-- Identify resource-heavy packs
-- Enforce denylisting via configuration
-- Feed monitoring dashboards
-
----
-
-## End-To-End Query Logging Flow
-
-```mermaid
-flowchart TD
- Config["ScheduledQuery"] --> Exec["SQL Execution"]
- Exec --> Results["QueryDataTyped"]
- Results --> QueryState["Query.addNewResults()"]
- QueryState --> Diff["DiffResults"]
- Diff --> LogItem["QueryLogItem"]
- LogItem --> Serialize["JSON Serialization"]
- Serialize --> Logger["LoggerPlugin"]
- Logger --> Sink["External Log System"]
-```
-
-### Snapshot Query Flow
-
-```mermaid
-flowchart TD
- SQ["ScheduledQuery snapshot=true"] --> Exec["Execute Query"]
- Exec --> Full["Full Result Set"]
- Full --> LogItem["QueryLogItem isSnapshot=true"]
- LogItem --> Logger["logSnapshot()"]
-```
-
-Snapshot queries bypass diff computation and emit complete result sets.
-
----
-
-## Relationship With Other Modules
-
-### SQL Engine And Virtual Tables
-
-Query execution originates from the SQL engine layer:
-
-- Virtual table resolution
-- SQLite execution
-- Result materialization
-
-See: [SQL Engine And Virtual Tables](../sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md)
-
-### Database And Storage Plugins
-
-Persistent state for query history and counters is managed by the storage abstraction.
-
-See: [Database And Storage Plugins](../database-and-storage-plugins/database-and-storage-plugins.md)
-
-### Configuration And Packs
-
-Scheduled queries and behavioral flags originate from configuration packs.
-
-See: [Configuration And Packs](../configuration-and-packs/configuration-and-packs.md)
-
-### Distributed Querying
-
-When queries are executed via distributed frameworks, results still flow through `QueryLogItem` and the logger interface.
-
-See: [Distributed Querying](../distributed-querying/distributed-querying.md)
-
----
-
-## Design Principles
-
-### 1. Pluggability
-
-Logging is abstracted via `LoggerPlugin` to allow:
-
-- TLS streaming
-- Filesystem logging
-- Syslog integration
-- Custom enterprise pipelines
-
-### 2. Efficiency
-
-- Differential logging reduces noise
-- Move semantics for result sets
-- CSV encoding for performance stats
-
-### 3. Deterministic Serialization
-
-All log structures have explicit JSON serializers to guarantee:
-
-- Backward compatibility
-- Stable schema
-- Predictable downstream parsing
-
-### 4. Observability-First Model
-
-Every query execution produces:
-
-- State delta
-- Execution metadata
-- Performance metrics
-- Host attribution
-
-This ensures complete auditability of query behavior.
-
----
-
-## Summary
-
-The **Logging And Query Observability** module transforms raw SQL execution results and runtime status events into structured, serialized, and pluggable log outputs.
-
-It provides:
-
-- Differential result tracking (`DiffResults`)
-- Query metadata encapsulation (`QueryLogItem`)
-- Performance telemetry (`QueryPerformance`)
-- Scheduling metadata (`ScheduledQuery`)
-- Extensible logging backends (`LoggerPlugin`)
-
-By cleanly separating execution, state management, serialization, and transport, this module forms the backbone of osqueryβs observability and audit pipeline.
\ No newline at end of file
diff --git a/docs/reference/architecture/osquery-shell-devtooling/osquery-shell-devtooling.md b/docs/reference/architecture/osquery-shell-devtooling/osquery-shell-devtooling.md
new file mode 100644
index 00000000000..8e1ed61e43c
--- /dev/null
+++ b/docs/reference/architecture/osquery-shell-devtooling/osquery-shell-devtooling.md
@@ -0,0 +1,353 @@
+# Osquery Shell Devtooling
+
+## Overview
+
+The **Osquery Shell Devtooling** module implements the interactive `osqueryi` shell experience. It provides:
+
+- An interactive SQLite-based SQL console
+- Multiple output rendering modes (pretty, column, line, list, CSV, JSON)
+- Meta-commands (e.g., `.tables`, `.schema`, `.show`, `.connect`)
+- Integration with extensions and remote query execution
+- Runtime profiling via CPU and wall-clock timing
+
+This module acts as a developer-facing entry point into the osquery runtime, bridging the SQL engine, registry, configuration system, extensions framework, and database backend into a cohesive CLI tool.
+
+Core components documented here:
+
+- `callback_data`
+- `prettyprint_data`
+- `rusage` (platform-dependent CPU accounting structure)
+
+---
+
+## Architectural Position
+
+The shell sits on top of the SQL engine and database manager while optionally delegating execution to extensions.
+
+```mermaid
+flowchart TD
+ User["User Terminal"] --> Shell["Osquery Shell Devtooling"]
+ Shell --> Parser["Meta Command Parser"]
+ Shell --> Executor["SQL Executor"]
+
+ Executor --> SQLite["SQLite Engine"]
+ SQLite --> VTables["Virtual Tables"]
+ VTables --> Registry["Table Registry"]
+
+ Executor --> DBManager["SQLiteDBManager"]
+ Executor --> Extensions["Extension Manager Client"]
+
+ Extensions --> RemoteExt["Remote Extension Socket"]
+```
+
+### Key Responsibilities
+
+1. Accept and parse interactive input
+2. Distinguish SQL statements from meta-commands
+3. Execute SQL locally or remotely
+4. Format and render result sets
+5. Provide runtime diagnostics and environment introspection
+
+---
+
+## Execution Flow
+
+The shell processes user input in a loop, accumulating SQL until it forms a complete statement or identifying a meta-command.
+
+```mermaid
+flowchart TD
+ A["Read Input Line"] --> B{"Starts With Dot?"}
+ B -->|"Yes"| C["Meta Command Handler"]
+ B -->|"No"| D["Accumulate SQL"]
+ D --> E{"Complete Statement?"}
+ E -->|"No"| A
+ E -->|"Yes"| F["Execute SQL"]
+ F --> G["shell_callback"]
+ G --> H["Render Output Mode"]
+ H --> A
+```
+
+### Major Functions
+
+- `process_input` β Main input loop
+- `do_meta_command` β Parses and dispatches dot commands
+- `shell_exec` β Executes SQL locally
+- `shell_exec_remote` β Executes SQL through extensions
+- `shell_callback` β Row-level result handler
+
+---
+
+## Core Data Structures
+
+### callback_data
+
+`callback_data` is the primary state container for the shell runtime.
+
+It maintains:
+
+- Output mode (`MODE_Pretty`, `MODE_Column`, etc.)
+- Header visibility
+- Field separator
+- Column widths
+- Null display value
+- Output file handle
+- Current prepared statement
+- Pretty-print state
+
+```mermaid
+classDiagram
+ class callback_data {
+ +int echoOn
+ +int mode
+ +int showHeader
+ +char separator[20]
+ +char nullvalue[20]
+ +FILE* out
+ +sqlite3_stmt* pStmt
+ +prettyprint_data* prettyPrint
+ }
+```
+
+This structure is passed through execution layers and into `shell_callback`, allowing output behavior to remain configurable and consistent.
+
+---
+
+### prettyprint_data
+
+`prettyprint_data` buffers result rows before formatting when in `MODE_Pretty`.
+
+It contains:
+
+- `QueryData results` β Collected rows
+- `vector columns` β Column order
+- `map lengths` β Computed width per column
+
+```mermaid
+classDiagram
+ class prettyprint_data {
+ +QueryData results
+ +vector columns
+ +map lengths
+ }
+
+ callback_data --> prettyprint_data
+```
+
+This buffering allows the shell to compute column widths dynamically before rendering formatted output.
+
+---
+
+### rusage
+
+The `rusage` structure tracks CPU time for the `.timer` feature.
+
+- On Unix: uses `getrusage`
+- On Windows: wraps `FILETIME`
+
+The timing workflow:
+
+```mermaid
+flowchart TD
+ Start["BEGIN_TIMER"] --> CaptureStart["Capture rusage + Wall Time"]
+ CaptureStart --> Execute["Run Query"]
+ Execute --> CaptureEnd["Capture End rusage"]
+ CaptureEnd --> Print["Print real, user, sys"]
+```
+
+The timer reports:
+
+- Real (wall-clock) time
+- User CPU time
+- System CPU time
+
+---
+
+## Output Modes
+
+The shell supports multiple rendering strategies.
+
+| Mode | Description |
+|------|-------------|
+| Pretty | Default aligned table format |
+| Column | Fixed-width columns |
+| Line | One column per line |
+| List | Separator-delimited rows |
+| CSV | Quoted CSV output |
+| JSON | JSON output via flags |
+
+### Rendering Strategy
+
+All result rows are passed through:
+
+```text
+shell_exec β shell_callback β output mode switch β formatting logic
+```
+
+In Pretty mode:
+
+1. Rows are buffered
+2. Column widths are computed
+3. Final formatted output is rendered
+4. Buffers are cleared
+
+---
+
+## Local vs Remote Execution
+
+The shell can execute queries either:
+
+- Directly against the embedded SQLite database
+- Through an extension socket using the extension client
+
+```mermaid
+flowchart LR
+ Query["SQL Query"] --> Check{"Connect Flag Set?"}
+ Check -->|"No"| LocalExec["shell_exec Local"]
+ Check -->|"Yes"| RemoteExec["shell_exec_remote"]
+ RemoteExec --> ExtClient["ExtensionManagerClient"]
+```
+
+### Remote Path
+
+- Connect via `FLAGS_connect`
+- Use `ExtensionManagerClient`
+- Retrieve rows and column types
+- Replay results through `shell_callback`
+
+This design preserves formatting behavior regardless of execution backend.
+
+---
+
+## Meta Commands
+
+Meta-commands begin with `.` and are handled separately from SQL.
+
+Examples:
+
+- `.tables` β List registered tables
+- `.schema` β Show CREATE statements
+- `.show` β Display runtime configuration
+- `.features` β Show enable or disable flags
+- `.connect` / `.disconnect` β Manage extension sockets
+- `.timer ON` β Enable profiling
+
+### Meta Command Processing
+
+```mermaid
+flowchart TD
+ Input[".command args"] --> Tokenize["Tokenize Arguments"]
+ Tokenize --> Match["Command Switch"]
+ Match --> Execute["Meta Handler Function"]
+ Execute --> Output["Print To Shell"]
+```
+
+Meta commands may:
+
+- Interact with the registry
+- Query internal virtual tables
+- Adjust shell runtime flags
+- Invoke SQL indirectly
+
+---
+
+## Input Handling and History
+
+Interactive input uses `linenoise` for:
+
+- Line editing
+- Command history
+- Table name completion
+
+Completion is implemented by querying the table registry and matching prefixes.
+
+Non-interactive mode supports piped input and file-driven execution.
+
+---
+
+## Integration with the Larger System
+
+The shell integrates tightly with:
+
+- SQL Engine and Virtual Tables
+- Database Backend (via `SQLiteDBManager`)
+- Extensions Framework
+- Configuration and Packs (via `runPack`)
+- Flags and Runtime Options
+
+### Pack Execution
+
+When `--pack` is provided:
+
+```mermaid
+flowchart TD
+ Start["Launch With Pack Flag"] --> LoadConfig["Load Packs From Config"]
+ LoadConfig --> Iterate["Iterate Scheduled Queries"]
+ Iterate --> Run["runQuery"]
+ Run --> Output["Formatted Results"]
+```
+
+This allows the shell to function as a lightweight pack executor for development and debugging.
+
+---
+
+## Error Handling
+
+Errors are managed at multiple levels:
+
+- SQLite prepare and step failures
+- Extension RPC failures
+- Incomplete SQL detection
+- Interrupt handling via SIGINT
+
+Behavior is influenced by:
+
+- `.bail ON|OFF`
+- Interactive vs non-interactive mode
+
+---
+
+## Key Design Characteristics
+
+### 1. Stateful Rendering Model
+
+All output behavior is driven by `callback_data`, enabling:
+
+- Consistent formatting
+- Mode switching at runtime
+- File redirection support
+
+### 2. Backend-Agnostic Execution
+
+The shell abstracts execution so that:
+
+- Local SQLite
+- Remote extension queries
+
+produce identical output paths.
+
+### 3. Developer-Centric Tooling
+
+Features like:
+
+- `.types`
+- `.features`
+- `.show`
+- `.timer`
+
+make the shell a debugging surface for the entire osquery stack.
+
+---
+
+## Summary
+
+The **Osquery Shell Devtooling** module provides a fully featured interactive SQL interface on top of the osquery runtime.
+
+It:
+
+- Bridges user input to the SQL engine
+- Supports local and extension-based execution
+- Implements flexible and extensible output formatting
+- Integrates with configuration, packs, and flags
+- Provides runtime diagnostics and profiling
+
+Architecturally, it is the developer-facing gateway into osqueryβs SQL engine, virtual tables, extension framework, and database layer β combining them into a cohesive, interactive experience.
\ No newline at end of file
diff --git a/docs/reference/architecture/remote-http-client/remote-http-client.md b/docs/reference/architecture/remote-http-client/remote-http-client.md
index 83b5f95de29..77c72143d13 100644
--- a/docs/reference/architecture/remote-http-client/remote-http-client.md
+++ b/docs/reference/architecture/remote-http-client/remote-http-client.md
@@ -1,345 +1,310 @@
# Remote Http Client
-The **Remote Http Client** module provides a general-purpose HTTP and HTTPS client implementation used across the system for secure remote communication. Built on top of Boost.Asio and Boost.Beast, it enables synchronous-style HTTP operations backed by asynchronous networking primitives, with full TLS support, timeout handling, redirect control, and proxy configuration.
+## Overview
-This module acts as the foundational networking layer for components that need to communicate with remote services, such as:
+The **Remote Http Client** module provides a general-purpose HTTP and HTTPS client implementation built on top of Boost.Asio and Boost.Beast. It is responsible for outbound network communication between osquery and remote services such as configuration endpoints, logging backends, distributed query servers, and metadata services.
-- [Distributed Querying](distributed-querying/distributed-querying.md)
-- [Logging and Query Observability](logging-and-query-observability/logging-and-query-observability.md)
-- [Configuration and Packs](configuration-and-packs/configuration-and-packs.md)
-
-It abstracts low-level socket management, TLS setup, request serialization, and response parsing into a reusable and secure HTTP client interface.
-
----
+This module abstracts:
-## 1. Purpose and Responsibilities
+- TCP connection management
+- TLS/SSL negotiation and certificate handling
+- HTTP request/response lifecycle
+- Header manipulation and URI parsing
+- Timeout and error handling
+- Optional proxy support
-The Remote Http Client module is responsible for:
+It serves as a foundational networking layer used by higher-level modules such as:
-- Creating and managing TCP and TLS connections
-- Executing HTTP methods: `GET`, `POST`, `PUT`, `HEAD`, `DELETE`
-- Managing request headers and body serialization
-- Parsing HTTP responses
-- Enforcing timeouts and connection lifecycle rules
-- Handling TLS verification, certificates, and cipher configuration
-- Supporting optional proxy routing
-- Supporting redirect and keep-alive behavior
-
-It provides a high-level API while internally orchestrating asynchronous Boost networking operations.
+- [Distributed TLS Plugin](distributed-tls-plugin/distributed-tls-plugin.md)
+- [Distributed Querying](distributed-querying/distributed-querying.md)
+- [Config Plugins](config-plugins/config-plugins.md)
---
-## 2. High-Level Architecture
-
-The module is centered around three main abstractions:
+## Architectural Context
-- `Client` β Connection lifecycle and HTTP execution engine
-- `HTTP_Request` β URI-aware request wrapper
-- `HTTP_Response` β Response wrapper with header iteration support
-
-### 2.1 Architectural Overview
+Within the osquery architecture, the Remote Http Client sits below plugin implementations that require remote communication but above the raw networking libraries (Boost.Asio, OpenSSL).
```mermaid
flowchart TD
- Caller["Caller Module"] --> Client["Client"]
- Client --> Options["Client::Options"]
- Client --> Request["HTTP_Request"]
- Client --> Response["HTTP_Response"]
-
- Client --> Resolver["TCP Resolver"]
- Client --> Socket["TCP Socket"]
- Client --> TLSSocket["SSL Stream"]
- Client --> Timer["Deadline Timer"]
-
- Request --> URI["URI Parser"]
- Response --> Headers["Header Iterator"]
+ ConfigPlugins["Config Plugins"] -->|"Fetch config"| RemoteHttpClient["Remote Http Client"]
+ DistributedTLS["Distributed TLS Plugin"] -->|"Send queries"| RemoteHttpClient
+ DistributedQuerying["Distributed Querying"] -->|"Submit results"| RemoteHttpClient
+
+ RemoteHttpClient -->|"TCP"| Asio["Boost Asio"]
+ RemoteHttpClient -->|"HTTP"| Beast["Boost Beast"]
+ RemoteHttpClient -->|"TLS"| OpenSSL["OpenSSL"]
```
-The `Client` orchestrates the network stack and delegates URI parsing to `HTTP_Request`, while wrapping Boost.Beast responses inside `HTTP_Response`.
+The module provides a clean interface for sending HTTP requests while encapsulating:
+
+- Asynchronous IO coordination
+- SSL context configuration
+- Request serialization and response parsing
+- Timeout enforcement
---
-## 3. Core Components
+## Core Components
-### 3.1 Client
+The Remote Http Client module revolves around the following key abstractions:
-The `Client` class implements a general-purpose HTTP/HTTPS client built on:
+### 1. Client
-- `boost::asio::io_context`
-- `boost::asio::ip::tcp::resolver`
-- `boost::asio::ip::tcp::socket`
-- `boost::asio::ssl::stream`
-- `boost::beast::http`
+`osquery::http::Client` is the main entry point for executing HTTP operations.
-It exposes the following public methods:
+It supports:
-- `get(Request&)`
-- `post(Request&, body, content_type)`
-- `put(Request&, body, content_type)`
-- `head(Request&)`
-- `delete_(Request&)`
+- `GET`
+- `POST`
+- `PUT`
+- `HEAD`
+- `DELETE`
Each method:
-1. Initializes the request
-2. Establishes or reuses a connection
-3. Sends the request asynchronously
-4. Waits for response or timeout
-5. Returns a `Response` object
-The destructor ensures that open sockets are closed safely.
+- Accepts a `Request`
+- Optionally accepts a body and content type
+- Returns a `Response` by value
+
+The Client encapsulates:
+
+- `boost::asio::io_context`
+- TCP resolver
+- TCP socket
+- Optional TLS socket wrapper
+- Deadline timer for timeouts
---
-### 3.2 Client Options
+### 2. Client Options
-The `Client::Options` class drives client behavior.
+The nested `Client::Options` class controls behavior and security settings.
-It supports configuration for:
+Supported configuration areas:
-- TLS enablement (`ssl_connection`)
-- Keep-alive behavior
-- Redirect following
-- Peer verification enforcement
-- Timeout configuration
+- TLS enable/disable (`ssl_connection`)
+- Certificate validation (`always_verify_peer`)
+- Custom CA verification path
+- Client certificate and private key
- Cipher selection
-- Certificate and private key files
-- CA verify path
- Proxy hostname
-- Remote hostname and port overrides
-
-#### Options Comparison
+- Remote hostname override
+- Remote port override
+- Timeout configuration
+- Redirect handling
+- Keep-alive support
-The equality operator allows the `Client` to detect configuration changes:
+Options are compared for equality to determine whether connection state must be refreshed.
```mermaid
flowchart LR
- OldOpts["Current Options"] --> Compare["operator=="]
- NewOpts["New Options"] --> Compare
- Compare -->|"Different"| Reconfigure["Reinitialize Connection"]
- Compare -->|"Same"| Reuse["Reuse Existing Settings"]
+ Options["Client Options"] --> SSL["SSL Configuration"]
+ Options --> Proxy["Proxy Settings"]
+ Options --> Timeout["Timeout Control"]
+ Options --> Redirects["Redirect Handling"]
+ Options --> KeepAlive["Keep Alive"]
```
-This prevents unnecessary TLS reconfiguration and socket churn.
+This design allows higher-level plugins to define secure communication policies without interacting directly with OpenSSL or Boost internals.
---
-### 3.3 HTTP_Request
-
-`HTTP_Request` extends Boost.Beast request objects with:
+### 3. HTTP Request
-- URI parsing support
-- Host, port, path extraction
-- Protocol detection
-- Header insertion via operator overloading
+`HTTP_Request` extends Boost.Beast request types and adds URI parsing capabilities.
-#### URI Handling
+Key features:
-The request wraps an internal `Uri` object and exposes:
+- Parses full URLs via `osquery::Uri`
+- Extracts host, port, path, query, fragment
+- Determines protocol (http or https)
+- Supports header injection via operator overloading
-- `remoteHost()`
-- `remotePort()`
-- `remotePath()`
-- `protocol()`
+Example header usage conceptually:
-This allows the `Client` to resolve and connect without requiring manual URL parsing.
+- Create `Header(name, value)`
+- Stream into request using `operator<<`
-#### Header Injection
+This allows concise header manipulation while maintaining strong typing.
-Headers are added using a helper struct:
-
-```text
-Request req("https://example.com/api");
-req << HTTP_Request::Header("Authorization", "Bearer token");
+```mermaid
+flowchart TD
+ Request["HTTP Request"] --> URI["URI Parser"]
+ Request --> Headers["Header Injection"]
+ Request --> Protocol["Scheme Detection"]
```
-This keeps header logic encapsulated within the request abstraction.
-
---
-### 3.4 HTTP_Response
+### 4. HTTP Response
-`HTTP_Response` extends Boost.Beast response objects and provides:
+`HTTP_Response` wraps the Beast response and provides:
-- `status()` β numeric HTTP status
-- `body()` β response body string
-- `headers()` β iterable header collection
+- `status()` for HTTP status code
+- `body()` for response payload
+- `headers()` iterator interface
-#### Header Iteration Model
+The nested `Headers` helper exposes:
+
+- Indexed header access
+- Iterable header enumeration
```mermaid
flowchart TD
- Response["HTTP_Response"] --> Headers["Headers"]
- Headers --> Iterator["Iterator"]
- Iterator --> Pair["(name, value)"]
+ Response["HTTP Response"] --> Status["Status Code"]
+ Response --> Body["Response Body"]
+ Response --> HeaderAccess["Header Iterator"]
```
-Example usage pattern:
-
-```text
-for (const auto& header : resp.headers()) {
- header.first;
- header.second;
-}
-```
-
-This abstraction avoids exposing raw Boost iterators directly.
-
---
-## 4. Request Lifecycle
-
-The `Client` wraps asynchronous Boost operations into a controlled flow.
-
-### 4.1 End-to-End Flow
-
-```mermaid
-sequenceDiagram
- participant Caller
- participant Client
- participant Resolver
- participant Server
-
- Caller->>Client: get(Request)
- Client->>Resolver: async_resolve()
- Resolver-->>Client: endpoints
- Client->>Server: async_connect()
- Client->>Server: async_write(request)
- Server-->>Client: HTTP response
- Client->>Server: async_read()
- Client-->>Caller: Response
-```
-
-### 4.2 TLS Flow (HTTPS)
+## Request Lifecycle
-If `ssl_connection` is enabled:
+The Client orchestrates a structured asynchronous workflow:
```mermaid
flowchart TD
- Connect["TCP Connect"] --> TLSCheck{"SSL Enabled?"}
- TLSCheck -->|"Yes"| Handshake["TLS Handshake"]
- TLSCheck -->|"No"| Plain["Plain HTTP"]
- Handshake --> Send["Send Request"]
- Plain --> Send
+ Start["Start Request"] --> Init["Initialize HTTP Request"]
+ Init --> Resolve["DNS Resolve"]
+ Resolve --> Connect["TCP Connect"]
+ Connect --> TLSCheck{{"TLS Enabled?"}}
+ TLSCheck -->|"Yes"| Handshake["SSL Handshake"]
+ TLSCheck -->|"No"| Write
+ Handshake --> Write["Async Write"]
+ Write --> Read["Async Read"]
+ Read --> Complete["Post Response Handler"]
+ Complete --> EndNode["END"]
```
-TLS configuration respects:
+### Key Internal Mechanisms
-- Cipher restrictions
-- Verify path
-- Server certificate pinning
-- Client certificate and private key
+- `createConnection()` selects direct or proxy connection
+- `encryptConnection()` upgrades TCP socket to SSL stream
+- `callNetworkOperation()` wraps async calls and timeout control
+- `timeoutHandler()` aborts operations if deadline expires
+- `postResponseHandler()` treats certain TLS short-read conditions as success
-Legacy SSL versions and MD5 are explicitly disabled at compile time.
+This architecture ensures:
----
+- Non-blocking network behavior
+- Deterministic timeout handling
+- Controlled error propagation
-## 5. Timeout and Error Handling
+---
-The client uses a `boost::asio::deadline_timer` to enforce network timeouts.
+## Timeout and Error Handling Model
-### 5.1 callNetworkOperation Wrapper
+The module uses a `boost::asio::deadline_timer` to enforce timeouts.
-The `callNetworkOperation` method:
+Network operations are wrapped inside `callNetworkOperation()` which:
1. Starts the timeout timer
2. Executes the async operation
-3. Waits for completion or timeout
-4. Cancels the opposing operation
-5. Sets the final error code
+3. Waits for either completion or timeout
+4. Cancels the alternate event
-```mermaid
-flowchart TD
- Start["Start Network Call"] --> Timer["Start Deadline Timer"]
- Timer --> Async["Async Operation"]
- Async --> Complete{"Completed?"}
- Complete -->|"Yes"| CancelTimer["Cancel Timer"]
- Complete -->|"No"| Timeout["Timer Fires"]
- Timeout --> Abort["Abort Socket"]
- CancelTimer --> Return["Return Response"]
- Abort --> Return
-```
+Error codes are stored in an internal `boost::system::error_code` field.
-### 5.2 TLS Short Read Handling
+This ensures:
-During TLS shutdown, some servers may not perform proper `shutdown()` calls. The client treats certain short-read conditions as success in post-response handling to avoid false-negative errors.
+- Unified timeout behavior
+- Safe cancellation
+- Clear separation between network and protocol errors
---
-## 6. Proxy and Metadata Support
+## TLS and Security Model
-### 6.1 Proxy Routing
+Security behavior is controlled via `Client::Options`.
-If a proxy hostname is configured:
+Security capabilities include:
-- Connection is established to the proxy
-- Request routing logic is adapted accordingly
+- Disable legacy SSL versions
+- Custom OpenSSL cipher configuration
+- Client certificate authentication
+- Custom CA verification paths
+- Enforced peer verification
-This enables deployment behind corporate proxies.
+The module explicitly disables insecure OpenSSL features such as SSLv2, SSLv3, MD5, and deprecated APIs.
-### 6.2 Cloud Metadata Authority
+Special handling is included for cloud metadata endpoints such as:
-The constant `kInstanceMetadataAuthority` (`169.254.169.254`) identifies the authority used by cloud metadata services (e.g., EC2, Azure).
+- `169.254.169.254`
-This allows safe and consistent access to instance metadata endpoints when required by higher-level modules.
+This authority constant supports integration with instance metadata services.
---
-## 7. Interaction with Other Modules
+## Interaction with Other Modules
-The Remote Http Client module acts as an infrastructure dependency for modules that require outbound HTTP communication.
+### Distributed TLS Plugin
-### 7.1 Distributed Querying
+The [Distributed TLS Plugin](distributed-tls-plugin/distributed-tls-plugin.md) uses the Remote Http Client to:
-The [Distributed Querying](distributed-querying/distributed-querying.md) module typically relies on HTTP transport (e.g., TLS-based distributed plugins) to:
-
-- Fetch remote queries
+- Fetch distributed queries
- Submit query results
+- Maintain secure TLS sessions
-The Remote Http Client provides the secure communication backbone for these operations.
-
-### 7.2 Logging and Query Observability
+### Distributed Querying
-The [Logging and Query Observability](logging-and-query-observability/logging-and-query-observability.md) module may use HTTP/TLS transports for remote log submission.
+The [Distributed Querying](distributed-querying/distributed-querying.md) module relies on this client for:
-The client ensures:
+- Remote query retrieval
+- Result delivery to orchestration servers
-- TLS enforcement
-- Certificate verification
-- Controlled timeout behavior
+### Config Plugins
-### 7.3 Configuration and Packs
+The [Config Plugins](config-plugins/config-plugins.md) leverage this module to:
-The [Configuration and Packs](configuration-and-packs/configuration-and-packs.md) module can retrieve configuration from remote endpoints via HTTP plugins. The Remote Http Client supplies:
+- Fetch remote configuration
+- Support dynamic config refresh
-- Secure GET/POST support
-- Redirect handling
-- Proxy awareness
+By isolating HTTP behavior in this module, higher-level components remain focused on business logic rather than networking.
---
-## 8. Security Model
+## Design Characteristics
+
+### 1. Abstraction Over Boost
+
+Consumers do not interact with:
+
+- Boost.Asio sockets
+- SSL stream configuration
+- HTTP parser internals
+
+All networking complexity is encapsulated.
-The module enforces multiple security measures:
+### 2. Explicit Security Configuration
-- SSLv2 and SSLv3 disabled
-- MD5 disabled
-- Deprecated OpenSSL features disabled
-- Optional strict peer verification
-- Optional custom cipher suites
-- Support for certificate pinning
+TLS behavior is not implicit. It must be enabled and configured via options.
-Security behavior is fully driven by `Client::Options`, allowing different modules to enforce different policies.
+### 3. Stateless Usage Model
+
+Each request:
+
+- Initializes request state
+- Establishes connection if needed
+- Executes operation
+- Cleans up socket on destruction
+
+### 4. Header and URI Convenience
+
+The extended request/response wrappers provide ergonomic access while preserving Beast compatibility.
---
-## 9. Summary
+## Summary
-The **Remote Http Client** module provides a robust, TLS-capable HTTP client abstraction built on Boost.Asio and Boost.Beast. It encapsulates:
+The **Remote Http Client** module provides the secure, asynchronous HTTP transport layer for osquery. It abstracts Boost networking primitives and OpenSSL configuration into a clean, high-level interface used by configuration, logging, and distributed execution subsystems.
-- Connection lifecycle management
-- TLS negotiation and verification
-- Asynchronous networking orchestration
-- Timeout enforcement
-- Request and response abstraction
+Its responsibilities include:
+
+- Secure HTTP and HTTPS communication
+- Timeout and error orchestration
+- Proxy and redirect support
+- TLS certificate management
+- URI parsing and header handling
-By centralizing HTTP communication logic, it ensures consistent, secure, and configurable remote connectivity across the system, serving as the networking foundation for distributed querying, logging, and remote configuration workflows.
+By centralizing outbound HTTP behavior, the module ensures consistent security posture and networking semantics across the entire osquery system.
\ No newline at end of file
diff --git a/docs/reference/architecture/sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md b/docs/reference/architecture/sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md
index e450a4f1d9d..4ae39df4826 100644
--- a/docs/reference/architecture/sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md
+++ b/docs/reference/architecture/sql-engine-and-virtual-tables/sql-engine-and-virtual-tables.md
@@ -2,22 +2,16 @@
## Overview
-The **Sql Engine And Virtual Tables** module is the execution core of osquery. It embeds and configures SQLite as an in-memory analytical engine and exposes operating system data through dynamically attached virtual tables.
+The **Sql Engine And Virtual Tables** module is the execution backbone of osquery. It embeds and manages an in-memory SQLite engine, exposes osquery tables as SQLite virtual tables, enforces SQL safety policies, and provides query planning and column type introspection.
-This module is responsible for:
+This module acts as the bridge between:
-- Managing and optimizing SQLite database instances
-- Enforcing SQL security through authorizers and allowlists
-- Attaching and detaching virtual tables backed by TablePlugin implementations
-- Planning and introspecting queries
-- Executing SQL statements and returning typed results
-- Bridging SQLiteβs virtual table API with osqueryβs plugin system
+- The **SQLite core engine** (query parsing, planning, execution)
+- The **Table Plugin framework** (C++ and extension-based tables)
+- The **Registry system** (plugin discovery and invocation)
+- Higher-level components such as logging, scheduling, and distributed querying
-It acts as the execution layer between:
-
-- Table plugins (from the Registry)
-- The scheduler and query interfaces
-- Extensions providing additional tables
+At runtime, nearly every query flows through this module.
---
@@ -25,26 +19,25 @@ It acts as the execution layer between:
```mermaid
flowchart TD
- Client["SQL Caller (Scheduler / CLI / Extension)"] --> SQLPlugin["SQLiteSQLPlugin"]
+ Client["SQL Caller\nScheduler, Shell, API"] --> SQLPlugin["SQLiteSQLPlugin"]
SQLPlugin --> DBManager["SQLiteDBManager"]
DBManager --> DBInstance["SQLiteDBInstance"]
- DBInstance --> SQLiteCore[("In-Memory SQLite Engine")]
-
- SQLiteCore --> VTabModule["sqlite3_module (Virtual Table Module)"]
- VTabModule --> VirtualTable["VirtualTable Wrapper"]
- VirtualTable --> TablePlugin["TablePlugin (Registry)"]
-
- SQLiteCore --> Planner["QueryPlanner"]
+ DBInstance --> SQLiteCore[("SQLite Engine")]
+ SQLiteCore --> VTableModule["sqlite3_module\nVirtual Table Layer"]
+ VTableModule --> TablePlugin["TablePlugin\nRegistry"]
+ TablePlugin --> DataSource["System Data Sources\nFilesystem, Processes, Network"]
```
-### Flow Summary
+### Key Responsibilities
-1. A SQL query is submitted via the SQL registry.
-2. `SQLiteSQLPlugin` obtains a database connection from `SQLiteDBManager`.
-3. The query is prepared and executed using `queryInternal`.
-4. When a virtual table is accessed, SQLite invokes the `sqlite3_module` callbacks.
-5. The virtual table implementation forwards execution to a `TablePlugin`.
-6. Results are returned to SQLite and then to the caller as typed rows.
+| Layer | Responsibility |
+|--------|----------------|
+| SQLiteSQLPlugin | Public SQL interface and plugin registration |
+| SQLiteDBManager | Connection lifecycle and resource management |
+| SQLiteDBInstance | Per-query SQLite wrapper with attach safety |
+| QueryPlanner | Query analysis and type inference |
+| sqlite3_module | SQLite virtual table implementation |
+| BaseCursor / VirtualTable | Runtime cursor and table state |
---
@@ -52,300 +45,283 @@ flowchart TD
### SQLiteSQLPlugin
-Implements the internal `sql` registry plugin.
+**Namespace:** `osquery.osquery.sql.sqlite_util.SQLiteSQLPlugin`
+
+The `SQLiteSQLPlugin` implements the `SQLPlugin` registry interface and provides:
+
+- `query()` β Execute SQL queries
+- `getQueryColumns()` β Infer result column names and types
+- `getQueryTables()` β Extract referenced tables
+- `attach()` β Attach virtual tables dynamically
+- `detach()` β Detach virtual tables
-**Responsibilities:**
+It is registered as an internal plugin under the name `sql`.
-- Execute SQL queries (`query`)
-- Introspect query columns (`getQueryColumns`)
-- Determine scanned tables (`getQueryTables`)
-- Attach/detach virtual tables dynamically
+### Execution Flow
-It acts as the primary entry point for SQL execution inside osquery.
+```mermaid
+flowchart TD
+ Start["Query Request"] --> GetDB["SQLiteDBManager.get()"]
+ GetDB --> UseCache["Set Cache Mode"]
+ UseCache --> Prepare["sqlite3_prepare_v2"]
+ Prepare --> Step["sqlite3_step"]
+ Step --> Rows["readRows()"]
+ Rows --> Finalize["sqlite3_finalize"]
+ Finalize --> Clear["Clear Affected Tables"]
+ Clear --> End["Return Status + Results"]
+```
---
-### SQLiteDBManager
+## SQLiteDBManager
+
+**Namespace:** `osquery.osquery.sql.sqlite_util.SQLiteDBManager`
-Singleton responsible for lifecycle and concurrency management of SQLite instances.
+The `SQLiteDBManager` is the central access point for SQLite resources.
-**Key Features:**
+### Responsibilities
-- Maintains a primary in-memory SQLite database
-- Creates transient database instances under contention
-- Applies memory optimizations (PRAGMA tuning)
-- Attaches all registered virtual tables
-- Enforces table enable/disable flags
+- Maintain the primary SQLite database instance
+- Provide transient instances during contention
+- Attach virtual tables automatically
+- Enforce enabled/disabled table policies
+- Manage SQLite memory limits
+
+### Connection Strategy
```mermaid
-flowchart LR
- Caller["Caller"] --> GetConn["SQLiteDBManager.get()"]
- GetConn --> PrimaryCheck{"Primary Available?"}
- PrimaryCheck -->|Yes| Primary["Primary SQLiteDBInstance"]
- PrimaryCheck -->|No| Transient["Transient SQLiteDBInstance"]
+flowchart TD
+ Request["get() or getConnection()"] --> CheckPrimary{"Primary DB Exists?"}
+ CheckPrimary -->|"No"| Init["openOptimized()"]
+ CheckPrimary -->|"Yes"| Reuse["Reuse Primary"]
+ Init --> Attach["attachVirtualTables()"]
+ Reuse --> ReturnPrimary["Return Primary or Transient"]
+ Attach --> ReturnPrimary
```
-This design minimizes resource usage while ensuring thread safety.
+If contention occurs, a transient `SQLiteDBInstance` is created with its own in-memory database.
---
-### SQLiteDBInstance
+## SQLiteDBInstance
+
+**Namespace:** `osquery.osquery.sql.sqlite_util.SQLiteDBInstance`
-RAII wrapper around a `sqlite3*` pointer.
+A RAII wrapper around `sqlite3*` that tracks:
-**Responsibilities:**
+- Query cache usage
+- Attached tables
+- Table attributes (such as EVENT_BASED)
+- Per-query constraint state
-- Provide safe access to SQLite handle
-- Manage locking and attach mutexes
-- Track affected virtual tables per query
-- Clear per-query table state
-- Support query result caching
+### Important Capabilities
-Each query receives a scoped database instance. On destruction:
+- `attachLock()` β Safe attach operations
+- `addAffectedTable()` β Track accessed tables
+- `clearAffectedTables()` β Reset state post-query
+- `useCache()` β Enable virtual table caching
-- Transient connections are closed
-- Primary connections remain managed
+This isolation allows safe concurrent execution across threads.
---
-### Security Enforcement (Authorizer)
+## SQLite Security Model
-The module enforces strict SQL safety using `sqliteAuthorizer`.
+The module enforces strict SQLite authorizer rules.
-**Allowlisted Actions:**
+### Authorizer: `sqliteAuthorizer`
-- `SELECT`, `READ`
-- Controlled `INSERT`, `UPDATE`, `DELETE`
-- Virtual table creation and drop
-- Limited `PRAGMA` commands
+Allowed operations include:
-**Explicitly Denied:**
+- SELECT
+- READ
+- INSERT, UPDATE, DELETE
+- CREATE/DROP TABLE or VIEW
+- CREATE/DROP VIRTUAL TABLE
+- FUNCTION calls
+- RECURSIVE queries
+- TRANSACTION
-- `SQLITE_ATTACH`
-- Any non-allowlisted opcode
+Explicitly denied:
-```mermaid
-flowchart TD
- Prepare["sqlite3_prepare_v2"] --> Authorizer["sqliteAuthorizer"]
- Authorizer -->|Allowed| Continue["Execute Statement"]
- Authorizer -->|Denied| Reject["SQLITE_DENY"]
-```
+- ATTACH DATABASE
+- Non-allowlisted PRAGMA calls
+
+If a forbidden action is attempted:
+
+- An error is logged
+- SQLite returns `SQLITE_DENY`
-This ensures osquery cannot be abused to modify arbitrary files or attach external databases.
+This prevents arbitrary file writes or unsafe database attachment.
---
-### QueryPlanner
+## Virtual Table Integration
-Performs query introspection using:
+**Namespace:** `osquery.osquery.sql.virtual_table`
-- `EXPLAIN QUERY PLAN`
-- `EXPLAIN`
+osquery tables are implemented as SQLite virtual tables.
-Used for:
+### Core Structures
-- Inferring column types for expressions
-- Determining scanned tables
-- Inspecting SQLite opcodes
+- `sqlite3_module` β SQLite callback table
+- `VirtualTable` β Wrapper around sqlite3_vtab
+- `BaseCursor` β Per-query cursor state
-The planner maps SQLite opcodes to osquery `ColumnType` using `kSQLOpcodes`.
+### Virtual Table Lifecycle
```mermaid
flowchart TD
- Query["SQL Query"] --> ExplainPlan["EXPLAIN QUERY PLAN"]
- Query --> Explain["EXPLAIN"]
- Explain --> OpcodeMap["kSQLOpcodes Mapping"]
- OpcodeMap --> TypeInference["Apply Column Types"]
+ Create["xCreate or xConnect"] --> Declare["sqlite3_declare_vtab"]
+ Declare --> BestIndex["xBestIndex"]
+ BestIndex --> Filter["xFilter"]
+ Filter --> Next["xNext"]
+ Next --> Column["xColumn"]
+ Column --> Rowid["xRowid"]
+ Rowid --> Eof["xEof"]
+ Eof --> Close["xClose"]
```
-This enables accurate schema introspection even when SQLite cannot directly determine expression types.
-
---
-### SQLInternal
+## Constraint Pushdown and Query Planning
-A lower-level SQL execution wrapper used internally.
+### xBestIndex
-**Capabilities:**
+`xBestIndex` evaluates WHERE constraints and determines:
-- Executes queries bypassing registry lookup
-- Returns typed results (`QueryDataTyped`)
-- Detects event-based tables
-- Escapes non-printable bytes
-- Calculates result size
+- Which columns are indexed
+- Required column presence
+- Estimated cost
+- Constraint ordering
-It is used when deeper inspection of query attributes is required.
+It builds:
----
+- ConstraintSet
+- UsedColumns
+- Bitset of accessed columns
-## Virtual Table Subsystem
+If required constraints are missing, cost is set to a high sentinel value.
-The Virtual Table subsystem connects SQLiteβs virtual table API with osqueryβs `TablePlugin` abstraction.
+### xFilter
-### VirtualTable
+`xFilter`:
-Wraps:
-
-- `sqlite3_vtab`
-- `VirtualTableContent` (metadata, schema, constraints)
-- Associated `SQLiteDBInstance`
-
-It maintains:
-
-- Column definitions
-- Aliases
-- Attributes (EVENT_BASED, USER_BASED, etc.)
-- Constraint tracking
+- Applies constraints to a `QueryContext`
+- Validates required columns
+- Executes the associated `TablePlugin`
+- Returns row sets or generator-backed cursors
---
-### BaseCursor
+## QueryPlanner and Type Inference
-Represents an active scan of a virtual table.
+**Namespace:** `osquery.osquery.sql.sqlite_util.QueryPlanner`
-Tracks:
+Used primarily for column introspection when SQLite cannot determine expression types.
-- Row set or generator
-- Cursor position
-- Current row
-- Planner ID
+### Strategy
-Supports both:
+1. Execute `EXPLAIN QUERY PLAN`
+2. Execute `EXPLAIN`
+3. Parse opcodes
+4. Map SQLite opcodes to osquery column types
-- Pre-generated row sets
-- Streaming generator-based tables
-
----
+The `Opcode` structure maps:
-### sqlite3_module Implementation
+- Register position (P1, P2, P3)
+- Resulting ColumnType
-Implements the SQLite virtual table callbacks:
+This enables inference of types for:
-- `xCreate`
-- `xBestIndex`
-- `xFilter`
-- `xNext`
-- `xColumn`
-- `xRowid`
-- `xUpdate`
+- Arithmetic operations
+- Aggregates
+- Comparators
+- CAST expressions
```mermaid
-sequenceDiagram
- participant SQLite
- participant Module as "sqlite3_module"
- participant Table as "TablePlugin"
-
- SQLite->>Module: xBestIndex
- Module->>SQLite: Constraint plan
-
- SQLite->>Module: xFilter
- Module->>Table: generate(context)
- Table-->>Module: Row set
- Module-->>SQLite: Rows
+flowchart TD
+ Query["User Query"] --> ExplainPlan["EXPLAIN QUERY PLAN"]
+ ExplainPlan --> Explain["EXPLAIN"]
+ Explain --> Parse["Parse Opcode Rows"]
+ Parse --> ApplyTypes["applyTypes()"]
+ ApplyTypes --> Columns["Typed Column Metadata"]
```
---
-## Constraint Optimization
+## SQLInternal
-`xBestIndex` evaluates constraints provided by SQLite and:
+`SQLInternal` is a lower-level execution wrapper that:
-- Identifies indexed and required columns
-- Calculates estimated cost
-- Rewrites `IN` constraints for optimized handling
-- Tracks used columns for projection pushdown
+- Returns `QueryDataTyped`
+- Tracks whether results are EVENT_BASED
+- Allows result escaping
+- Computes result size
-If required constraints are missing:
+### Additional Features
-- Cost is set to a maximum
-- Query may fail with `SQLITE_CONSTRAINT`
+- `escapeResults()` β Escapes non-printable bytes
+- `getSize()` β Computes result memory size
+- `eventBased()` β Detect event-based tables
-This enables efficient filtering at the table implementation level.
+This is used by higher-level components that need typed results.
---
-## Query Execution Flow
-
-```mermaid
-flowchart TD
- Start["Query Submitted"] --> Prepare["sqlite3_prepare_v2"]
- Prepare --> Execute["sqlite3_step Loop"]
- Execute -->|Virtual Table Access| VTab
- VTab --> xBestIndex
- xBestIndex --> xFilter
- xFilter --> Generate["TablePlugin.generate()"]
- Generate --> Rows["Return Rows"]
- Rows --> Finalize["sqlite3_finalize"]
- Finalize --> End["Results Returned"]
-```
-
----
-
-## Extension and Writable Tables
-
-If a table originates from an extension:
-
-- `xUpdate` is enabled
-- INSERT / UPDATE / DELETE are forwarded
-- Parameters are serialized into JSON
-- Responses are validated
-
-This allows controlled writable virtual tables.
-
----
+## Attach and Detach Mechanism
-## Memory and Performance Optimizations
+Virtual tables can be dynamically attached:
-When opening the in-memory database:
+- `attachTableInternal()` registers a SQLite module
+- `detachTableInternal()` drops the temp virtual table
-- `journal_mode=OFF`
-- `synchronous=OFF`
-- `auto_vacuum=FULL`
-- Custom function extensions registered
-- Authorizer installed
+Attachment occurs during:
-Additionally:
+- Startup
+- Extension loading
+- Explicit attach requests
-- SQLite soft heap limit configured
-- Memory released after each query
-- Transient DB instances created only under contention
+All operations are guarded by `attachLock()`.
---
-## Interaction with Other Modules
+## Integration with Other Modules
The Sql Engine And Virtual Tables module integrates closely with:
-- Table plugins (Registry)
-- Extensions (for remote virtual tables)
-- Logging and query observability (for execution results)
-- Eventing framework (for event-based tables)
-- Core initialization (for flag configuration)
+- Core runtime for shutdown handling and flags
+- Logging for error reporting
+- Extensions framework for external tables
+- Database backend for persistent storage tables
+- Events framework for EVENT_BASED table semantics
-It does not duplicate table logic; it provides the execution infrastructure.
+It forms the execution boundary between SQL logic and system instrumentation.
---
-## Key Design Principles
+## Design Principles
-1. **Security First** β Strict SQLite authorizer and allowlists
-2. **In-Memory Execution** β No persistent database files
-3. **Plugin-Based Tables** β Data sources abstracted behind registry
-4. **Query-Aware Optimization** β Constraint and projection pushdown
-5. **Thread-Safe Resource Management** β Managed primary DB with transient fallback
-6. **Extension-Friendly** β Writable virtual tables supported
+1. Security-first SQL execution
+2. Deterministic virtual table behavior
+3. Thread-safe database access
+4. Efficient constraint pushdown
+5. Minimal SQLite surface exposure
+6. Strong separation between SQL layer and table logic
---
## Summary
-The **Sql Engine And Virtual Tables** module is the execution backbone of osquery.
+The **Sql Engine And Virtual Tables** module transforms osquery into a SQL-powered operating system instrumentation engine.
-It transforms SQLite into a secure, extensible, in-memory analytics engine that:
+It:
-- Executes SQL safely
-- Dynamically attaches system-backed virtual tables
-- Optimizes query plans
-- Bridges plugins and extensions with SQLiteβs execution engine
+- Embeds and secures SQLite
+- Converts table plugins into virtual tables
+- Plans and executes queries
+- Infers types for expressions
+- Enforces constraint semantics
+- Provides safe attach/detach mechanisms
-Without this module, osquery would not be able to expose system data through a unified SQL interface.
+Without this module, osquery would be a collection of system probes. With it, those probes become a relational query engine capable of complex joins, filtering, aggregation, and introspection.
\ No newline at end of file
diff --git a/libraries/cmake/source/augeas/generated/linux/aarch64/code/.parser.md b/libraries/cmake/source/augeas/generated/linux/aarch64/code/.parser.md
index a9ebb2bd29b..cc323666012 100644
--- a/libraries/cmake/source/augeas/generated/linux/aarch64/code/.parser.md
+++ b/libraries/cmake/source/augeas/generated/linux/aarch64/code/.parser.md
@@ -1,46 +1,34 @@
-Auto-generated Bison parser interface header for the Augeas lens language (`augl`) parser, defining token types, semantic value types, and location tracking structures used by the generated LALR(1) parser.
+Auto-generated Bison parser interface header for the `augl` language parser, defining token types, semantic value types, and location tracking structures used by the Yacc/Bison-generated parser.
## Key Components
-### Token Enum (`yytokentype`)
-Defines all terminal tokens recognized by the lexer:
-
-| Token | Value | Description |
-|---|---|---|
-| `DQUOTED` | 258 | Double-quoted string literal |
-| `REGEXP` | 259 | Regular expression literal |
-| `LIDENT` / `UIDENT` / `QIDENT` | 260β262 | Lower/Upper/Qualified identifiers |
-| `ARROW` | 263 | `->` arrow operator |
-| `KW_MODULE` β¦ `KW_AFTER` | 264β275 | Language keywords |
-
-### Semantic Value Union (`YYSTYPE`)
-Holds the value associated with each parsed token or grammar rule:
-
-- `struct term *term` β AST expression node
-- `struct type *type` β Type annotation node
-- `struct ident *ident` β Identifier reference
-- `struct tree *tree` β Parse tree node
-- `char *string` β String value
-- `regexp` β Struct with `pattern` (string) and `nocase` (int) flag
-- `int intval` β Integer literal
-- `enum quant_tag quant` β Quantifier (`*`, `+`, `?`)
-
-### Location Type (`YYLTYPE`)
-Tracks source positions with `first_line`, `first_column`, `last_line`, `last_column` for error reporting.
-
-### Parser Entry Point
-```c
-int augl_parse(struct term **term, yyscan_t scanner);
-```
-
-### Scanner State (`struct state`)
-```c
-struct state {
- struct info *info; // Source file info
- unsigned int comment_depth; // Nested comment tracking
-};
-```
+**Token Enum (`yytokentype`)**
+Defines lexical tokens for the `augl` grammar:
+- Literals: `DQUOTED` (258), `REGEXP` (259)
+- Identifiers: `LIDENT`, `UIDENT`, `QIDENT`
+- Keywords: `KW_MODULE`, `KW_AUTOLOAD`, `KW_LET`, `KW_LET_REC`, `KW_IN`, `KW_STRING`, `KW_REGEXP`, `KW_LENS`, `KW_TEST`, `KW_GET`, `KW_PUT`, `KW_AFTER`
+- Operators: `ARROW`
+
+**`YYSTYPE` (Semantic Value Union)**
+Holds the value associated with each parsed token:
+- `struct term *term` β AST term node
+- `struct type *type` β type annotation
+- `struct ident *ident` β identifier reference
+- `struct tree *tree` β parse tree node
+- `char *string` β string literal value
+- `regexp` β struct with `nocase` flag and `pattern` string
+- `int intval` β integer value
+- `enum quant_tag quant` β quantifier tag
+
+**`YYLTYPE` (Location Type)**
+Tracks source location (line/column range) for error reporting.
+
+**`struct state`**
+Custom scanner state holding a `struct info *` and `comment_depth` counter for nested comment tracking.
+
+**`augl_parse()`**
+Entry point for the parser.
## Usage Example
@@ -48,18 +36,19 @@ struct state {
#include "parser.h"
#include "info.h"
-struct term *result = NULL;
-yyscan_t scanner;
+int parse_augeas_lens(const char *filename) {
+ struct term *term = NULL;
+ yyscan_t scanner;
-augl_lex_init(&scanner);
-// configure scanner input ...
+ /* Initialize scanner with custom state */
+ struct state st = { .info = make_info(filename), .comment_depth = 0 };
-int rc = augl_parse(&result, scanner);
-if (rc == 0 && result != NULL) {
- // process the parsed AST term
-}
+ augl_lex_init(&scanner);
+ augl_set_extra(&st, scanner);
-augl_lex_destroy(scanner);
-```
+ int result = augl_parse(&term, scanner);
-> **Note:** This file is auto-generated by GNU Bison 3.0.4 from `parser.y`. Do not edit directly β modify the grammar source and regenerate.
\ No newline at end of file
+ augl_lex_destroy(scanner);
+ return result; /* 0 on success */
+}
+```
\ No newline at end of file
diff --git a/libraries/cmake/source/augeas/generated/linux/x86_64/code/.parser.md b/libraries/cmake/source/augeas/generated/linux/x86_64/code/.parser.md
index b54e83a94b8..cc997ce3172 100644
--- a/libraries/cmake/source/augeas/generated/linux/x86_64/code/.parser.md
+++ b/libraries/cmake/source/augeas/generated/linux/x86_64/code/.parser.md
@@ -1,74 +1,60 @@
-Auto-generated Bison parser interface header defining token types, semantic value union (`YYSTYPE`), location tracking (`YYLTYPE`), and scanner state for parsing Augeas lens definition files.
+Auto-generated Bison parser interface header defining token types, semantic value unions, and location tracking structures for the Augeas lens language parser.
## Key Components
### Token Definitions (`yytokentype` enum)
+Lexer tokens for the lens grammar:
+
| Token | Value | Description |
-|---|---|---|
+|-------|-------|-------------|
| `DQUOTED` | 258 | Double-quoted string literal |
| `REGEXP` | 259 | Regular expression literal |
-| `LIDENT` / `UIDENT` / `QIDENT` | 260β262 | Lower/Upper/Qualified identifiers |
+| `LIDENT` | 260 | Lowercase identifier |
+| `UIDENT` | 261 | Uppercase identifier |
+| `QIDENT` | 262 | Qualified identifier |
| `ARROW` | 263 | `->` arrow operator |
-| `KW_MODULE` β¦ `KW_AFTER` | 264β275 | Language keywords |
-
-### `YYSTYPE` β Semantic Value Union
-Holds the value associated with each parsed token or grammar rule:
-
-```c
-union YYSTYPE {
- struct term *term; // Expression/term node
- struct type *type; // Type annotation
- struct ident *ident; // Identifier reference
- struct tree *tree; // Parse tree node
- char *string; // String value
- struct {
- int nocase; // Case-insensitive flag
- char *pattern; // Regex pattern string
- } regexp;
- int intval; // Integer literal
- enum quant_tag quant; // Quantifier (*, +, ?)
-};
-```
-
-### `YYLTYPE` β Location Tracking
+| `KW_MODULE`β`KW_AFTER` | 264β275 | Language keywords |
+
+### `YYSTYPE` (Semantic Value Union)
+Holds per-token semantic data during parsing:
+- `term` β parsed expression/term node
+- `type` β type annotation node
+- `ident` β identifier node
+- `tree` β AST tree node
+- `string` β raw string value
+- `regexp` β struct with `pattern` (char*) and `nocase` (int) flag
+- `intval` β integer literal value
+- `quant` β quantifier tag (`*`, `+`, `?`)
+
+### `YYLTYPE` (Location Tracking)
Tracks source positions for error reporting:
+- `first_line` / `first_column` β token start
+- `last_line` / `last_column` β token end
-```c
-typedef struct YYLTYPE {
- int first_line;
- int first_column;
- int last_line;
- int last_column;
-} YYLTYPE;
-```
-
-### `state` β Custom Scanner State
-Carries context between the lexer and parser:
-
-```c
-struct state {
- struct info *info; // Source file metadata
- unsigned int comment_depth; // Nested comment tracking
-};
-```
+### `struct state`
+Custom scanner state (defined via `%code provides`):
+- `info` β pointer to `struct info` (file/source metadata)
+- `comment_depth` β tracks nested comment depth for lexer
## Usage Example
```c
#include "parser.h"
-
-// Access token location after parsing
-void report_error(YYLTYPE *loc, const char *msg) {
- fprintf(stderr, "Error at line %d, col %d: %s\n",
- loc->first_line, loc->first_column, msg);
+#include "info.h"
+
+/* Access token location in a grammar action */
+YYLTYPE loc = yylloc;
+fprintf(stderr, "Error at line %d, col %d\n",
+ loc.first_line, loc.first_column);
+
+/* Inspect semantic value type */
+YYSTYPE val = yylval;
+if (current_token == REGEXP) {
+ printf("Pattern: %s (nocase: %d)\n",
+ val.regexp.pattern,
+ val.regexp.nocase);
}
-
-// Initialize scanner state before invoking yyparse()
-struct state scanner_state = {
- .info = load_info("myfile.aug"),
- .comment_depth = 0
-};
```
-> **Note:** This file is auto-generated by GNU Bison 2.4.1 from `parser.y`. Do not edit directly β modify the grammar source instead.
\ No newline at end of file
+> **Note:** This file is auto-generated by GNU Bison 2.4.1 from `parser.y`. Edit `parser.y` directly rather than modifying this header.
\ No newline at end of file
diff --git a/libraries/cmake/source/augeas/generated/macos/aarch64/code/.parser.md b/libraries/cmake/source/augeas/generated/macos/aarch64/code/.parser.md
index e4d32a0c30c..20a23379fda 100644
--- a/libraries/cmake/source/augeas/generated/macos/aarch64/code/.parser.md
+++ b/libraries/cmake/source/augeas/generated/macos/aarch64/code/.parser.md
@@ -1,41 +1,33 @@
-Auto-generated Bison parser interface header for the `augl` grammar, defining token types, semantic value unions, and location tracking structures used by the Augeas lens language parser.
+Auto-generated Bison parser interface header for the `augl` language parser, defining token types, semantic value types, and location tracking structures used by the Augeas lens grammar.
## Key Components
-### Token Enum (`yytokentype`)
+**Token Enum (`yytokentype`)**
Defines all terminal tokens recognized by the lexer:
-
-| Token | Value | Description |
-|---|---|---|
-| `DQUOTED` | 258 | Double-quoted string literal |
-| `REGEXP` | 259 | Regular expression literal |
-| `LIDENT` / `UIDENT` / `QIDENT` | 260β262 | Lower/upper/qualified identifiers |
-| `ARROW` | 263 | `->` arrow operator |
-| `KW_MODULE` β¦ `KW_AFTER` | 264β275 | Language keywords |
-
-### Semantic Value Union (`YYSTYPE`)
-Holds the value of each parsed token/rule:
-
-| Field | Type | Purpose |
-|---|---|---|
-| `term` | `struct term *` | AST term node |
-| `type` | `struct type *` | Type annotation |
-| `ident` | `struct ident *` | Identifier reference |
-| `tree` | `struct tree *` | Parse tree node |
-| `regexp` | `struct { int nocase; char *pattern; }` | Regex with case flag |
-| `quant` | `enum quant_tag` | Quantifier (`*`, `+`, `?`) |
-
-### Location Type (`YYLTYPE`)
-Tracks source positions with `first_line`, `first_column`, `last_line`, `last_column` for error reporting.
-
-### Scanner State (`struct state`)
-Custom lexer state carrying an `info` context pointer and `comment_depth` for nested comment handling.
-
-### Entry Point
-```c
-int augl_parse(struct term **term, yyscan_t scanner);
-```
+- Literals: `DQUOTED` (258), `REGEXP` (259)
+- Identifiers: `LIDENT` (260), `UIDENT` (261), `QIDENT` (262)
+- Keywords: `KW_MODULE`, `KW_AUTOLOAD`, `KW_LET`, `KW_LET_REC`, `KW_IN`, `KW_STRING`, `KW_REGEXP`, `KW_LENS`, `KW_TEST`, `KW_GET`, `KW_PUT`, `KW_AFTER`
+- Operators: `ARROW` (263)
+
+**`YYSTYPE` Union**
+Semantic value type carrying one of:
+- `struct term *` β AST term node
+- `struct type *` β type annotation
+- `struct ident *` β identifier
+- `struct tree *` β tree node
+- `char *string` β string literal
+- `regexp` struct (pattern + `nocase` flag)
+- `int intval`, `enum quant_tag quant`
+
+**`YYLTYPE` Struct**
+Source location tracking with `first_line`, `first_column`, `last_line`, `last_column`.
+
+**`struct state`**
+Custom scanner state holding an `info` pointer and `comment_depth` counter for nested comment handling.
+
+**`augl_parse()`**
+Main parser entry point.
## Usage Example
@@ -44,24 +36,17 @@ int augl_parse(struct term **term, yyscan_t scanner);
#include "info.h"
int parse_lens_file(const char *filename) {
- struct term *root = NULL;
+ struct term *result = NULL;
yyscan_t scanner;
- /* Initialize scanner state with source info */
- struct state st = {
- .info = make_info(filename),
- .comment_depth = 0
- };
-
- augl_lex_init(&scanner);
- augl_set_extra(&st, scanner);
-
- /* Run the parser; result stored in root */
- int rc = augl_parse(&root, scanner);
-
- augl_lex_destroy(scanner);
- return rc; /* 0 on success */
+ /* Initialize scanner, then parse */
+ int rc = augl_parse(&result, scanner);
+ if (rc != 0) {
+ /* handle parse error */
+ }
+ /* use result AST term */
+ return rc;
}
```
-> **Note:** Do not use any symbols prefixed with `yy_` or `YY_` β these are private Bison internals subject to change without notice.
\ No newline at end of file
+> **Note:** This file is auto-generated by GNU Bison 3.8.2 from `parser.y`. Edit the grammar source, not this header directly.
\ No newline at end of file
diff --git a/libraries/cmake/source/augeas/generated/macos/x86_64/code/.parser.md b/libraries/cmake/source/augeas/generated/macos/x86_64/code/.parser.md
index aebbb9ace67..ce8566c7439 100644
--- a/libraries/cmake/source/augeas/generated/macos/x86_64/code/.parser.md
+++ b/libraries/cmake/source/augeas/generated/macos/x86_64/code/.parser.md
@@ -1,38 +1,36 @@
-Auto-generated Bison parser interface header for the Augeas lens language (`augl`) grammar, defining token types, semantic value union, and location tracking structures used by the LALR(1) parser.
+Auto-generated Bison parser interface header for the `augl` grammar, defining token types, semantic value types, and location tracking structures used by the Augeas lens language parser.
## Key Components
-### Token Enum (`yytokentype`)
+### Token Types (`yytokentype` enum)
Defines all terminal symbols recognized by the lexer:
-
-| Token | Value | Description |
-|---|---|---|
-| `DQUOTED` | 258 | Double-quoted string literal |
-| `REGEXP` | 259 | Regular expression literal |
-| `LIDENT` / `UIDENT` / `QIDENT` | 260β262 | Lower/upper/qualified identifiers |
-| `ARROW` | 263 | `->` operator |
-| `KW_MODULE` β¦ `KW_AFTER` | 264β275 | Language keywords |
-
-### Semantic Value Union (`YYSTYPE`)
-Holds the parsed value for each grammar symbol:
-
-- `struct term *term` β AST expression node
-- `struct type *type` β type annotation node
-- `struct ident *ident` β identifier node
-- `struct tree *tree` β parse tree node
-- `char *string` β raw string value
-- `regexp` β struct with `nocase` flag and `pattern` string
-- `int intval` β integer literal
-- `enum quant_tag quant` β quantifier (`*`, `+`, `?`)
-
-### Location Type (`YYLTYPE`)
-Tracks source positions with `first_line`, `first_column`, `last_line`, `last_column` for error reporting.
-
-### Scanner State (`struct state`)
-Custom lexer state attached to the reentrant scanner, carrying an `info` context and `comment_depth` counter for nested comment handling.
-
-### Parser Entry Point
+- **Literals:** `DQUOTED` (258), `REGEXP` (259)
+- **Identifiers:** `LIDENT` (260), `UIDENT` (261), `QIDENT` (262)
+- **Operators:** `ARROW` (263)
+- **Keywords:** `KW_MODULE`, `KW_AUTOLOAD`, `KW_LET`, `KW_LET_REC`, `KW_IN`, `KW_STRING`, `KW_REGEXP`, `KW_LENS`, `KW_TEST`, `KW_GET`, `KW_PUT`, `KW_AFTER`
+
+### `YYSTYPE` (Semantic Value Union)
+Holds the value associated with each parsed token or grammar rule:
+
+| Field | Type | Purpose |
+|-------|------|---------|
+| `term` | `struct term *` | AST term node |
+| `type` | `struct type *` | Type annotation |
+| `ident` | `struct ident *` | Identifier reference |
+| `tree` | `struct tree *` | Parse tree node |
+| `string` | `char *` | String literal value |
+| `regexp` | struct | Pattern + `nocase` flag |
+| `intval` | `int` | Integer literal |
+| `quant` | `enum quant_tag` | Quantifier (`*`, `+`, `?`) |
+
+### `YYLTYPE` (Location Tracking)
+Tracks source positions for error reporting via `first_line`, `first_column`, `last_line`, `last_column`.
+
+### `struct state`
+Custom scanner state carrying `struct info *` and a `comment_depth` counter for nested comment handling.
+
+### Entry Point
```c
int augl_parse(struct term **term, yyscan_t scanner);
```
@@ -47,18 +45,16 @@ int parse_lens_file(const char *filename) {
struct term *result = NULL;
yyscan_t scanner;
- /* Initialize reentrant scanner, then invoke parser */
+ /* Initialize scanner, then invoke parser */
augl_lex_init(&scanner);
-
int rc = augl_parse(&result, scanner);
+ augl_lex_destroy(scanner);
+
if (rc == 0 && result != NULL) {
- /* Walk the resulting AST term */
- process_term(result);
+ /* result points to the parsed AST term */
}
-
- augl_lex_destroy(scanner);
return rc;
}
```
-> **Note:** This file is auto-generated by GNU Bison 3.8.2 from `parser.y`. Do not edit directly β modify the grammar source instead and regenerate.
\ No newline at end of file
+> **Note:** This file is auto-generated by GNU Bison 3.8.2 from `parser.y`. Do not edit directly β modify the grammar source instead.
\ No newline at end of file
diff --git a/openframe/.openframe_authorization_manager.md b/openframe/.openframe_authorization_manager.md
index 5203e846d2e..8f4e178397e 100644
--- a/openframe/.openframe_authorization_manager.md
+++ b/openframe/.openframe_authorization_manager.md
@@ -1,34 +1,35 @@
-Manages the OpenFrame authorization token used for authentication with OpenFrame services. This singleton-style class provides controlled access to storing and retrieving the auth token via a provider-based pattern.
+Singleton-style manager class for storing and retrieving the OpenFrame authorization token used to authenticate with OpenFrame services.
## Key Components
| Symbol | Type | Description |
-|---|---|---|
-| `OpenframeAuthorizationManager` | Class | Non-copyable token manager; instantiation restricted to `OpenframeAuthorizationManagerProvider` |
-| `updateToken(token)` | Method | Replaces the stored authorization token |
-| `getToken()` | Method | Returns the current authorization token |
-| `token_` | Private Field | Internal string storage for the token |
-| `OpenframeAuthorizationManagerProvider` | Friend Class | Sole class permitted to construct/destroy instances |
+|--------|------|-------------|
+| `OpenframeAuthorizationManager` | Class | Non-copyable manager for the OpenFrame auth token |
+| `updateToken(token)` | Method | Replaces the currently stored authorization token |
+| `getToken()` | Method | Returns the current authorization token as a `std::string` |
+| `token_` | Private field | Internal storage for the authorization token |
+| `OpenframeAuthorizationManagerProvider` | Friend class | Sole class permitted to construct this manager |
## Usage Example
```cpp
-// Access is granted only through the provider β never constructed directly.
-// Typical usage via the provider pattern:
+#include "openframe_authorization_manager.h"
+
+// Access is provided via the friend provider β direct construction is private.
+// Typical usage through the provider:
OpenframeAuthorizationManager& manager = provider.getManager();
// Store a new token received from OpenFrame auth flow
manager.updateToken("Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...");
-// Retrieve the token for an outbound API request
+// Retrieve token for use in outbound requests
std::string token = manager.getToken();
-httpClient.setHeader("Authorization", token);
```
-## Design Notes
+## Notes
-- **Non-copyable** (`boost::noncopyable`): Prevents accidental token duplication across object copies.
-- **Private constructor/destructor**: Enforces that only `OpenframeAuthorizationManagerProvider` can create or destroy instances, ensuring centralized lifecycle management.
-- **`osquery` namespace**: Integrates with the broader osquery agent infrastructure used by the OpenFrame platform.
\ No newline at end of file
+- The class inherits from `boost::noncopyable`, preventing accidental copy or assignment β enforcing a single shared instance pattern.
+- Construction and destruction are `private`, delegating lifecycle management exclusively to `OpenframeAuthorizationManagerProvider`.
+- Lives within the `osquery` namespace, integrating with the broader osquery/OpenFrame telemetry and endpoint management stack.
\ No newline at end of file
diff --git a/openframe/.openframe_encryption_service.md b/openframe/.openframe_encryption_service.md
index 7319497e8f5..88abf86af71 100644
--- a/openframe/.openframe_encryption_service.md
+++ b/openframe/.openframe_encryption_service.md
@@ -1,17 +1,16 @@
-AES-256-GCM decryption service header for the OpenFrame platform, providing symmetric key encryption utilities via OpenSSL.
+Declares the `OpenframeEncryptionService` class, providing AES-256-GCM decryption and Base64 decoding utilities for securing data within the OpenFrame platform.
## Key Components
-| Symbol | Type | Description |
-|---|---|---|
-| `OpenframeEncryptionService` | Class | Main encryption service wrapping OpenSSL EVP AES-GCM operations |
-| `OpenframeEncryptionService(secret)` | Constructor | Initializes the service with a symmetric secret key |
-| `decrypt(data)` | Method | Decrypts a Base64-encoded AES-256-GCM ciphertext, returns plaintext string |
-| `base64Decode(encoded)` | Method | Decodes a Base64 string into raw bytes |
-| `handleOpenSSLError()` | Private Method | Throws `std::runtime_error` with OpenSSL error details on failure |
+| Member | Type | Description |
+|--------|------|-------------|
+| `OpenframeEncryptionService(secret)` | Constructor | Initializes the service with a secret key string |
+| `decrypt(data)` | Public method | Decrypts a Base64-encoded AES-GCM payload; throws `std::runtime_error` on failure |
+| `base64Decode(encoded)` | Public method | Decodes a Base64 string into raw bytes |
+| `handleOpenSSLError()` | Private method | Extracts and throws OpenSSL error details |
| `KEY_SIZE` | Constant | 32 bytes (256-bit AES key) |
-| `IV_SIZE` | Constant | 12 bytes (96-bit GCM nonce) |
+| `IV_SIZE` | Constant | 12 bytes (96-bit GCM IV) |
| `TAG_SIZE` | Constant | 16 bytes (128-bit GCM authentication tag) |
## Usage Example
@@ -22,22 +21,24 @@ AES-256-GCM decryption service header for the OpenFrame platform, providing symm
int main() {
// Initialize with a 256-bit secret key
- OpenframeEncryptionService enc("my-32-byte-secret-key-goes-here!");
+ OpenframeEncryptionService enc_service("your-32-byte-secret-key-here!!");
- // Decrypt Base64-encoded AES-256-GCM payload
+ // Decrypt a Base64-encoded AES-GCM payload
try {
- std::string ciphertext = "BASE64_ENCODED_ENCRYPTED_PAYLOAD==";
- std::string plaintext = enc.decrypt(ciphertext);
+ std::string encrypted_payload = "BASE64_ENCODED_ENCRYPTED_DATA";
+ std::string plaintext = enc_service.decrypt(encrypted_payload);
std::cout << "Decrypted: " << plaintext << std::endl;
} catch (const std::runtime_error& e) {
std::cerr << "Decryption failed: " << e.what() << std::endl;
}
- // Standalone Base64 decode
- std::vector raw = enc.base64Decode("SGVsbG8gV29ybGQ=");
-
- return 0;
+ // Decode raw Base64 data
+ std::vector raw = enc_service.base64Decode("SGVsbG8gV29ybGQ=");
}
```
-> **Note:** The secret passed to the constructor must produce a 256-bit (32-byte) derived key. Any OpenSSL failure during decryption throws `std::runtime_error` via `handleOpenSSLError()`.
\ No newline at end of file
+## Notes
+
+- Requires **OpenSSL** (`libssl-dev`) linked at build time (`-lssl -lcrypto`)
+- The secret passed to the constructor must produce a valid 256-bit key after internal derivation
+- Authentication tag verification is enforced by AES-GCM, ensuring both confidentiality and integrity
\ No newline at end of file
diff --git a/openframe/.openframe_token_extractor.md b/openframe/.openframe_token_extractor.md
index 2d3e20928e6..8d6291dbf74 100644
--- a/openframe/.openframe_token_extractor.md
+++ b/openframe/.openframe_token_extractor.md
@@ -1,16 +1,11 @@
-Provides a class interface for reading and decrypting authentication tokens stored in encrypted files, bridging file I/O with the OpenFrame encryption layer.
+Declares the `OpenframeTokenExtractor` class, responsible for reading and decrypting authentication tokens from a file using an injected encryption service.
## Key Components
-### `OpenframeTokenExtractor` (class)
-
-| Member | Type | Description |
-|--------|------|-------------|
-| `OpenframeTokenExtractor(encryption_service, token_file_path)` | Constructor | Initializes the extractor with a shared encryption service and the path to the token file |
-| `extractToken()` | `std::string` | Reads the token file, decrypts its contents via the injected `OpenframeEncryptionService`, and returns the plaintext token |
-| `token_file_path_` | `std::string` (private) | Stored path to the encrypted token file on disk |
-| `encryption_service_` | `std::shared_ptr` (private) | Shared ownership of the encryption service used for decryption |
+- **`OpenframeTokenExtractor`** β Main class that wraps token file access and decryption logic.
+- **Constructor** β Accepts a shared `OpenframeEncryptionService` instance and the path to the token file.
+- **`extractToken()`** β Public method that reads the token file and returns the decrypted token string.
## Usage Example
@@ -18,20 +13,15 @@ Provides a class interface for reading and decrypting authentication tokens stor
#include "openframe_token_extractor.h"
#include "openframe_encryption_service.h"
-// Create a shared encryption service
-auto enc_service = std::make_shared(/* config */);
-
-// Instantiate the extractor with the service and token file path
-OpenframeTokenExtractor extractor(enc_service, "/etc/openframe/auth.token");
+auto enc_service = std::make_shared(/* ... */);
+OpenframeTokenExtractor extractor(enc_service, "/etc/openframe/token.enc");
-// Extract and decrypt the token
std::string token = extractor.extractToken();
-
-// Use the plaintext token for authenticated API calls
+// Use token for authenticated API calls
```
## Notes
-- Uses shared ownership (`std::shared_ptr`) for the encryption service, making it safe to share one service instance across multiple extractors.
-- The destructor is defaulted, so no manual resource cleanup is required.
-- Depends on `openframe_encryption_service.h` β ensure the encryption service is properly initialized before calling `extractToken()`.
\ No newline at end of file
+- Depends on `OpenframeEncryptionService` via dependency injection, keeping encryption logic decoupled from file I/O.
+- The encryption service is held as a `std::shared_ptr`, allowing shared ownership across multiple consumers.
+- The token file path is stored at construction time; create a new instance to switch paths.
\ No newline at end of file
diff --git a/openframe/.openframe_token_refresher.md b/openframe/.openframe_token_refresher.md
index 3ec04ff3e39..0c3acadcf64 100644
--- a/openframe/.openframe_token_refresher.md
+++ b/openframe/.openframe_token_refresher.md
@@ -1,17 +1,14 @@
-Manages background token refresh for OpenFrame authentication by running a periodic refresh loop in a dedicated thread.
+Manages background token refresh for the OpenFrame authorization system, periodically re-extracting authentication tokens at a fixed interval using a dedicated thread.
## Key Components
-| Symbol | Type | Description |
-|---|---|---|
-| `OpenframeTokenRefresher` | Class | Background service that periodically refreshes authentication tokens |
-| `OpenframeTokenRefresher(extractor)` | Constructor | Accepts a shared `OpenframeTokenExtractor` instance |
-| `start()` | Method | Spawns the background refresh thread |
-| `stop()` | Method | Signals the refresh loop to terminate and joins the thread |
-| `process()` | Private Method | Core refresh loop executed on the background thread |
-| `running_` | `std::atomic` | Thread-safe flag controlling the refresh loop lifecycle |
-| `extractor_` | `shared_ptr` | Token extraction dependency injected at construction |
+- **`OpenframeTokenRefresher`** β Main class responsible for running a background refresh loop
+ - `OpenframeTokenRefresher(extractor)` β Constructor accepting a shared `OpenframeTokenExtractor` instance
+ - `start()` β Launches the background refresh thread
+ - `stop()` β Signals the thread to terminate and joins it cleanly
+ - `process()` β Private method containing the periodic refresh loop logic
+- **Thread-safety primitives** β Uses `std::atomic running_` for safe shutdown signaling and `std::mutex mutex_` for state protection
## Usage Example
@@ -19,20 +16,21 @@ Manages background token refresh for OpenFrame authentication by running a perio
#include "openframe_token_refresher.h"
#include "openframe_token_extractor.h"
-// Inject extractor and start background refresh
+// Create the extractor and pass it to the refresher
auto extractor = std::make_shared();
osquery::OpenframeTokenRefresher refresher(extractor);
-refresher.start(); // begins periodic token refresh loop
+// Start background token refresh
+refresher.start();
-// ... application runs ...
+// ... application runs, tokens are refreshed automatically ...
-refresher.stop(); // gracefully stops the background thread
+// Gracefully stop the refresh thread on shutdown
+refresher.stop();
```
## Notes
-- Lives in the `osquery` namespace alongside other OpenFrame authentication components
-- Depends on `OpenframeTokenExtractor` for token retrieval and `OpenframeAuthorizationManager` for token storage/validation
-- Uses `std::atomic` for lock-free lifecycle control and `std::mutex` for any shared state access within `process()`
-- `stop()` should always be called before destruction to avoid detached thread behavior
\ No newline at end of file
+- The refresher holds a `shared_ptr` to the extractor, ensuring the extractor remains alive for the full lifetime of the refresh thread
+- `stop()` should always be called before destruction to avoid dangling thread resources (the destructor calls it implicitly via RAII)
+- Operates within the `osquery` namespace, integrating with the broader OpenFrame authorization pipeline via `openframe_authorization_manager.h`
\ No newline at end of file
diff --git a/osquery/carver/.carver.md b/osquery/carver/.carver.md
index 50e1e949180..3f2931b66f1 100644
--- a/osquery/carver/.carver.md
+++ b/osquery/carver/.carver.md
@@ -3,38 +3,32 @@ Defines the file carving subsystem for osquery, providing classes and utilities
## Key Components
-### `CarverRunnable`
-Abstract base class extending `InternalRunnable`. Manages the carver dispatch lifecycle via a static `running_` atomic flag. The `start()` method serially processes all pending carve requests; subclasses must implement `doCarve()`.
-
-### `CarverRunner`
-Templated concrete runner that instantiates a carver of type `T` for each request. Designed to allow test-fake injection by swapping the carver type. Tracks the number of carves attempted in the current run cycle via `carves()`.
-
-### `Carver`
-Core carving class. Constructed with a set of file paths, a GUID, and a request ID. Orchestrates the full pipeline:
-
-| Method | Description |
-|---|---|
-| `carve()` | End-to-end entry point: carve β compress β POST |
-| `createPaths()` | Sets up temp directory, archive, and compressed output paths |
-| `carveAll()` | Blockwise-copies source files into a temp directory |
-| `blockwiseCopy()` | Low-level copy using `FLAGS_carver_block_size` (default 8 KB) |
-| `postCarve()` | POSTs the compressed archive to the configured TLS endpoint |
-
-### `scheduleCarves()`
-Free function called by the scheduler to dispatch a `CarverRunner` if one is not already running.
+| Symbol | Type | Description |
+|--------|------|-------------|
+| `CarverRunnable` | Abstract class | `InternalRunnable` subclass that serially processes pending carve requests; exposes a static `running()` flag |
+| `CarverRunner` | Class template | Concrete `CarverRunnable` that instantiates a carver of type `T` per request and tracks carve count |
+| `Carver` | Base class | Implements the full carve lifecycle: path setup, blockwise file copy, tar/zstd compression, and HTTP POST |
+| `scheduleCarves()` | Free function | Entry point called by the scheduler; dispatches a `CarverRunner` if none is active |
## Usage Example
```cpp
-// Dispatch carves from the scheduler
+// Dispatch pending carves from the scheduler
osquery::scheduleCarves();
-// Direct use of the Carver pipeline (e.g., in tests via CarverRunner)
-std::set paths = {"/etc/passwd", "/var/log/syslog"};
-osquery::Carver carver(paths, "guid-1234", "request-5678");
+// --- Or use CarverRunner directly in tests ---
+std::set paths = {"/etc/hosts", "/etc/passwd"};
+std::string guid = "abc-123";
+std::string requestId = "req-456";
+
+osquery::CarverRunner runner;
+osquery::Status status = runner.doCarve(paths, guid, requestId);
-Status status = carver.carve(); // carve β archive β compress β POST
if (!status.ok()) {
LOG(ERROR) << "Carve failed: " << status.getMessage();
}
-```
\ No newline at end of file
+
+size_t attempted = runner.carves(); // 1
+```
+
+> **Note:** `Carver::postCarve()` is `virtual`, allowing test subclasses to override the HTTP POST step without hitting a real endpoint. The carve block size is controlled by the `FLAGS_carver_block_size` flag (default 8 KB).
\ No newline at end of file
diff --git a/osquery/carver/.carver_utils.md b/osquery/carver/.carver_utils.md
index da5baa2fa91..840ecb42fa9 100644
--- a/osquery/carver/.carver_utils.md
+++ b/osquery/carver/.carver_utils.md
@@ -1,40 +1,40 @@
-Utility header providing core primitives for osquery's file carving subsystem β constants, database helpers, and scheduling functions used across carver components.
+Utility header for osquery's file carving subsystem, providing constants, a template function, and declarations for scheduling and managing file carve operations.
## Key Components
### Constants
-
-| Constant | Value | Purpose |
-|---|---|---|
-| `kCarvePathPrefix` | `"osquery_carve_"` | Temp filesystem directory prefix |
-| `kCarveNamePrefix` | `"carve_"` | Tar archive filename prefix |
-| `kCarverDBPrefix` | `"carves."` | Database key namespace prefix |
-| `kCarverStatusSuccess` | `"SUCCESS"` | Terminal success state |
-| `kCarverStatusScheduled` | `"SCHEDULED"` | Pending/queued state |
-
-### Globals
-
-- **`kCarverPendingCarves`** (`std::atomic`) β Optimization flag for `CarverRunner`; avoids spinning up scheduler threads when no carves are queued.
+| Name | Description |
+|------|-------------|
+| `kCarvePathPrefix` | Temp filesystem directory prefix (`osquery_carve_`) |
+| `kCarveNamePrefix` | Tar archive name prefix (`carve_`) |
+| `kCarverDBPrefix` | Database key prefix for carve entries (`carves.`) |
+| `kCarverStatusSuccess` | Status string for completed carves (`SUCCESS`) |
+| `kCarverStatusScheduled` | Status string for pending carves (`SCHEDULED`) |
+| `kCarverPendingCarves` | Atomic bool flag used by `CarverRunner` to skip idle thread cycles |
### Functions
-- **`updateCarveValue(guid, key, value)`** β Template function that reads a carve entry from the database by GUID, parses its JSON, updates a single key, and writes it back.
-- **`createCarveGuid()`** β Generates and returns a new UUID string for identifying a carve request.
-- **`carvePaths(paths, request_id, carve_guid)`** β Schedules a deferred file carve for the given paths; populates `carve_guid` on success and returns a `Status`.
+- **`updateCarveValue`** β Template function that updates a single key-value attribute on a carve entry stored in the database, identified by GUID. Handles JSON deserialization, mutation, and re-serialization internally.
+- **`createCarveGuid()`** β Generates and returns a new UUID string to identify a carve request.
+- **`carvePaths()`** β Schedules a file carve for a set of paths. Carving is intentionally deferred to avoid blocking query execution or causing parallel carve contention.
## Usage Example
-```c
-// Schedule a carve for specific paths
-std::set targets = {"/etc/passwd", "/var/log/auth.log"};
-std::string guid;
+```cpp
+#include
-Status s = carvePaths(targets, "incident-42", guid);
+// Schedule a carve for a set of paths
+std::string carve_guid;
+std::set paths = {"/etc/passwd", "/var/log/syslog"};
+
+Status s = osquery::carvePaths(paths, "incident-42", carve_guid);
if (s.ok()) {
- // Update a metadata field on the scheduled carve
- updateCarveValue(guid, "priority", std::string("high"));
+ LOG(INFO) << "Carve scheduled with GUID: " << carve_guid;
}
+
+// Later, update an attribute on that carve entry
+osquery::updateCarveValue(carve_guid, "status", osquery::kCarverStatusSuccess);
```
-> **Note:** `carvePaths` is non-blocking by design β actual carving is deferred to the scheduler to avoid blocking query execution or parallelism issues.
\ No newline at end of file
+> **Note:** `carvePaths` is non-blocking by design β actual carving is dispatched by the `CarverRunner` scheduler, not executed inline. The `kCarverPendingCarves` atomic flag controls whether the runner thread activates on its 60-second cycle.
\ No newline at end of file
diff --git a/osquery/config/.config.md b/osquery/config/.config.md
index c963af8f4d6..168ea85f750 100644
--- a/osquery/config/.config.md
+++ b/osquery/config/.config.md
@@ -1,52 +1,34 @@
-Programmatic representation of osquery's runtime configuration, providing a singleton interface for loading, updating, validating, and querying configuration state including scheduled queries, file watches, and performance metrics.
+Programmatic representation of osquery's runtime configuration, providing a singleton `Config` class that manages query schedules, file watches, config source hashing, performance tracking, and plugin-driven config parsing.
## Key Components
-### `Config` (Singleton Class)
-The core configuration manager. Access via `Config::get()`.
-
-**Public Methods:**
-
-| Method | Description |
-|---|---|
-| `update(config)` | Apply new configuration data from a source map |
-| `load()` | Check for a registered config plugin and trigger initial load |
-| `refresh()` | Re-invoke the config plugin's `genConfig` (supports periodic refresh) |
-| `recordQueryPerformance(...)` | Store pre/post process metrics for a scheduled query |
-| `recordQueryStart(name)` | Mark a query as "dirty" (running) for crash detection |
-| `genHash(hash)` | Compute SHA1 over all config sources |
-| `hashSource(source, content)` | Hash a single source; returns `true` if content changed |
-| `scheduledQueries(predicate)` | Iterate scheduled queries via callback |
-| `packs(predicate)` | Iterate all loaded packs via callback |
-| `files(predicate)` | Iterate watched file categories via callback |
-| `getPerformanceStats(name, predicate)` | Retrieve `QueryPerformance` stats for a named query |
-| `getParser(name)` | Fetch a registered `ConfigParserPlugin` by name |
-| `validateConfig(document)` | Validate JSON depth and root type |
-| `restoreConfigBackup()` | Retrieve config persisted in the backing database |
-
-### `kExecutingQuery`
-Global string constant identifying the currently executing scheduled query.
-
----
+- **`Config`** β Singleton class (non-copyable) encapsulating all configuration state
+- **`Config::get()`** β Static singleton accessor
+- **`Config::update()`** β Applies new config data from a source map
+- **`Config::recordQueryPerformance()`** β Records pre/post execution metrics for scheduled queries
+- **`Config::recordQueryStart()`** β Marks a query as "dirty" (in-flight) in the backing store
+- **`Config::genHash()` / `hashSource()`** β SHA1 hashing of config content per source
+- **`Config::scheduledQueries()`** β Iterates scheduled queries via a predicate callback
+- **`Config::packs()`** β Iterates registered query packs via a predicate callback
+- **`Config::files()`** β Iterates watched file categories via a predicate callback
+- **`Config::getParser()`** β Retrieves a named `ConfigParserPlugin` from the registry
+- **`Config::validateConfig()`** β Validates JSON document structure and depth
+- **`Config::restoreConfigBackup()`** β Retrieves config persisted in the database
+- **`kExecutingQuery`** β Global string holding the currently executing query name
## Usage Example
```cpp
// Access the singleton
-auto& cfg = Config::get();
+auto& c = Config::get();
-// Iterate all scheduled queries
-cfg.scheduledQueries([](std::string name, const ScheduledQuery& query) {
- LOG(INFO) << "Query: " << name << " interval: " << query.interval;
-});
+// Load and apply config from a plugin source
+c.load();
-// Iterate watched file categories
-cfg.files([](const std::string& category,
- const std::vector& paths) {
- for (const auto& p : paths) {
- LOG(INFO) << category << ": " << p;
- }
+// Iterate all scheduled queries
+c.scheduledQueries([](std::string name, const ScheduledQuery& query) {
+ LOG(INFO) << "Scheduled query: " << name;
});
// Retrieve performance stats for a specific query
@@ -54,9 +36,9 @@ Config::getPerformanceStats("my_query", [](const QueryPerformance& perf) {
LOG(INFO) << "Executions: " << perf.executions;
});
-// Restore backed-up config from database
-auto result = Config::restoreConfigBackup();
-if (result) {
- cfg.update(result.take());
-}
+// Iterate watched file categories
+c.files([](const std::string& category,
+ const std::vector& paths) {
+ LOG(INFO) << "Category: " << category;
+});
```
\ No newline at end of file
diff --git a/osquery/config/.packs.md b/osquery/config/.packs.md
index 153833cf1fe..d9cc7768789 100644
--- a/osquery/config/.packs.md
+++ b/osquery/config/.packs.md
@@ -1,51 +1,50 @@
-Defines the `Pack` class and related utilities for managing osquery query packs β collections of scheduled queries with platform/version constraints and discovery logic.
+Defines the `Pack` class and related utilities for managing osquery query packs β groupings of scheduled queries with discovery conditions, platform requirements, and execution scheduling logic.
## Key Components
-### `PackStats` struct
-Tracks discovery query execution statistics: `total`, `hits`, and `misses` counts.
+### `PackStats`
+Simple struct tracking discovery query execution metrics: `total`, `hits`, and `misses` counts.
-### `Pack` class
+### `Pack` (class)
Non-copyable class representing a query pack loaded from configuration.
| Method | Description |
|---|---|
| `initialize()` | Parses and loads pack content from a `rapidjson::Value` |
-| `shouldPackExecute()` | Determines if the pack should run on this host |
-| `checkPlatform()` | Validates platform compatibility |
+| `shouldPackExecute()` | Determines if the pack is eligible to run on this host |
+| `checkPlatform()` | Validates OS compatibility |
| `checkVersion()` | Validates minimum osquery version requirement |
-| `checkDiscovery()` | Runs discovery queries to determine pack applicability |
-| `isActive()` | Returns active state without triggering discovery queries |
-| `getSchedule()` | Returns the vector of `ScheduledQuery` entries |
-| `getStats()` | Returns accumulated `PackStats` |
+| `checkDiscovery()` | Runs discovery queries to confirm pack applicability |
+| `isActive()` | Returns cached active state without re-running discovery |
+| `getSchedule()` | Returns the list of `ScheduledQuery` entries in the pack |
+| `getStats()` | Returns discovery execution statistics |
### Free Functions
| Function | Description |
|---|---|
-| `splayValue(original, splay_percent)` | Generates a splayed interval from a base interval and percent |
-| `restoreSplayedValue(name, interval)` | Retrieves or generates a cached splay for a name/interval pair |
+| `splayValue(original, splay_percent)` | Generates a randomized interval offset within a given splay percentage |
+| `restoreSplayedValue(name, interval)` | Retrieves or generates a deterministic cached splay for a query name/interval pair |
## Usage Example
```cpp
#include
-// Construct a pack from parsed JSON
-rapidjson::Value packObj; // populated from config
-osquery::Pack pack("my_pack", "config_source", packObj);
+// Construct a pack from a JSON object
+rapidjson::Document doc;
+doc.Parse(packJsonString.c_str());
-// Check if the pack should run on this host
+osquery::Pack pack("my_pack", "config_source", doc);
+
+// Check if this pack should run on the current host
if (pack.shouldPackExecute()) {
- for (const auto& query : pack.getSchedule()) {
- // queue query for execution
- }
+ for (const auto& query : pack.getSchedule()) {
+ // Process each scheduled query
+ }
}
-// Generate a splayed interval (e.g., 10% splay on 60s interval)
-uint64_t splayed = osquery::splayValue(60, 10);
-
-// Retrieve or create a stable cached splay
-uint64_t stable = osquery::restoreSplayedValue("my_pack_query", 60);
+// Get a splayed interval for a 60s query with 10% splay
+uint64_t interval = osquery::restoreSplayedValue("my_query", 60);
```
\ No newline at end of file
diff --git a/osquery/config/tests/.test_utils.md b/osquery/config/tests/.test_utils.md
index 0771b51ebad..f5c3ebfb923 100644
--- a/osquery/config/tests/.test_utils.md
+++ b/osquery/config/tests/.test_utils.md
@@ -1,37 +1,37 @@
-Utility header providing test infrastructure helpers for osquery configuration and pack loading in unit tests.
+Utility header providing test infrastructure helpers for osquery's configuration and pack-related unit tests.
## Key Components
| Symbol | Type | Description |
-|---|---|---|
-| `getTestConfigDirectory()` | Function | Returns path to the test configuration directory |
-| `getTestHelperScriptsDirectory()` | Function | Returns path to the test helper scripts directory |
-| `getTestConfigMap()` | Function | Builds a config map from a file, mapping source name to JSON content |
-| `getExamplePacksConfig()` | Function | Returns a sample packs configuration as a `JSON` object |
-| `getUnrestrictedPack()` | Function | Returns a pack with no platform/version restrictions |
-| `getRestrictedPack()` | Function | Returns a pack with platform/version restrictions applied |
-| `getPackWithDiscovery()` | Function | Returns a pack containing discovery queries |
-| `getPackWithValidDiscovery()` | Function | Returns a pack with a discovery query expected to pass |
-| `getPackWithFakeVersion()` | Function | Returns a pack targeting a non-existent/fake osquery version |
+|--------|------|-------------|
+| `getTestConfigDirectory()` | Function | Returns the filesystem path to the test configuration directory |
+| `getTestHelperScriptsDirectory()` | Function | Returns the filesystem path to test helper scripts |
+| `getTestConfigMap()` | Function | Builds a config map from a file, mapping a static source name to its JSON content |
+| `getExamplePacksConfig()` | Function | Returns a `JSON` object representing an example packs configuration |
+| `getUnrestrictedPack()` | Function | Returns a `JSON` object for a pack with no restrictions |
+| `getRestrictedPack()` | Function | Returns a `JSON` object for a pack with restrictions applied |
+| `getPackWithDiscovery()` | Function | Returns a `JSON` object for a pack containing discovery queries |
+| `getPackWithValidDiscovery()` | Function | Returns a `JSON` object for a pack with valid discovery queries |
+| `getPackWithFakeVersion()` | Function | Returns a `JSON` object for a pack targeting a non-existent/fake version |
## Usage Example
```c
#include "test_utils.h"
-// Resolve test config files at runtime
-auto config_dir = osquery::getTestConfigDirectory();
-auto config_map = osquery::getTestConfigMap("example_config.conf");
+// Resolve test asset paths
+boost::filesystem::path configDir = osquery::getTestConfigDirectory();
+boost::filesystem::path scriptsDir = osquery::getTestHelperScriptsDirectory();
-// Load fixture packs for scheduler/config unit tests
-osquery::JSON unrestricted = osquery::getUnrestrictedPack();
-osquery::JSON restricted = osquery::getRestrictedPack();
-osquery::JSON discovered = osquery::getPackWithValidDiscovery();
-```
+// Load a config map from a test file
+auto configMap = osquery::getTestConfigMap("example.conf");
-## Notes
+// Access fixture pack configurations
+osquery::JSON unrestrictedPack = osquery::getUnrestrictedPack();
+osquery::JSON restrictedPack = osquery::getRestrictedPack();
+osquery::JSON discoveryPack = osquery::getPackWithValidDiscovery();
+osquery::JSON fakePack = osquery::getPackWithFakeVersion();
+```
-- All functions are declared inside the `osquery` namespace.
-- Path helpers return `const` references β do not store the result beyond test scope.
-- Pack fixture functions return `JSON` objects (from `osquery/utils/json/json.h`) and are intended exclusively for use in unit/integration tests.
\ No newline at end of file
+> All symbols are declared within the `osquery` namespace. This header is intended exclusively for use in test targets and should not be included in production code.
\ No newline at end of file
diff --git a/osquery/core/.flags.md b/osquery/core/.flags.md
index 3168ef7b20f..9192a889854 100644
--- a/osquery/core/.flags.md
+++ b/osquery/core/.flags.md
@@ -1,55 +1,54 @@
-Declares osquery's flag management system, wrapping gflags to support categorized, queryable, and runtime-updatable configuration options across shell, CLI, extension, and hidden flag contexts.
+Defines osquery's flag management system, wrapping Google's gflags library with additional metadata tracking for shell, extension, CLI, and hidden flag categories.
## Key Components
### Structs
-- **`FlagDetail`** β Metadata for a flag: description, and boolean markers (`shell`, `external`, `cli`, `hidden`)
-- **`FlagInfo`** β Full flag snapshot including type, description, default value, current value, and its `FlagDetail`
+- **`FlagDetail`** β Metadata for a flag: description, and boolean attributes (`shell`, `external`, `cli`, `hidden`)
+- **`FlagInfo`** β Full flag info including type, description, default value, current value, and a `FlagDetail`
-### Class: `Flag` (singleton, non-copyable)
+### Class: `Flag` (Singleton, noncopyable)
| Method | Description |
-|---|---|
-| `create()` | Registers a new named flag with its detail metadata |
-| `createAlias()` | Registers a gflags alias pointing to an existing flag |
-| `flags()` | Returns a map of all registered flags and their info |
-| `getValue()` / `getInt32Value()` | Retrieves flag value by name |
-| `getDefaultValue()` | Retrieves the default value for a flag |
-| `updateValue()` | Updates a flag's value at runtime |
-| `isDefault()` | Checks if a flag still holds its default value |
-| `getType()` / `getDescription()` | Introspection helpers |
-| `isCLIOnlyFlag()` | Returns true if the flag is CLI/flagfile-only |
+|--------|-------------|
+| `create()` | Registers a new flag with its metadata |
+| `createAlias()` | Creates a gflags alias pointing to an existing flag |
+| `flags()` | Returns all registered flags as a `map` |
+| `getValue()` / `getInt32Value()` | Retrieves current flag value by name |
+| `getDefaultValue()` | Retrieves the default value, returns `Status` |
+| `updateValue()` | Updates a flag's runtime value |
+| `isDefault()` | Checks if a flag is still at its default |
+| `isCLIOnlyFlag()` | Returns true if flag cannot be set via config options |
| `printFlags()` | Prints help output, filterable by shell/external/cli |
-| `resetCustomFlags()` | Clears custom flags (used by fuzzers) |
+| `resetCustomFlags()` | Clears custom flags map (used by fuzzers) |
### Macros
-| Macro | Behavior |
-|---|---|
-| `FLAG(t,n,v,d)` | Standard flag β settable via flagfile, CLI, or config options |
-| `SHELL_FLAG` | Only available in `osqueryi` |
+| Macro | Description |
+|-------|-------------|
+| `FLAG(t,n,v,d)` | Standard flag usable in flagfile, CLI, or config options |
+| `SHELL_FLAG` | Only available in `osqueryi` shell |
| `EXTENSION_FLAG` | Only available to extensions |
-| `CLI_FLAG` | Cannot be set via config `options` |
+| `CLI_FLAG` | CLI/flagfile only β not settable via config `"options"` |
| `HIDDEN_FLAG` | Excluded from `--help` output |
## Usage Example
-```cpp
-// Declare flags in a .cpp file
-FLAG(bool, enable_feature, false, "Enable the experimental feature");
-CLI_FLAG(string, config_path, "/etc/osquery/osquery.conf", "Path to config file");
-SHELL_FLAG(int32, query_timeout, 300, "Query timeout in seconds (osqueryi only)");
-
-// Read a flag value at runtime
-std::string path = Flag::getValue("config_path");
-
-// Update a flag value programmatically
-Status s = Flag::updateValue("enable_feature", "true");
-if (!s.ok()) {
- LOG(WARNING) << "Failed to update flag: " << s.getMessage();
-}
-
-// Check if a flag was explicitly set or still at default
-if (Flag::isDefault("query_timeout")) {
- LOG(INFO) << "Using default query timeout";
-}
+```c
+// Declare flags in any translation unit
+FLAG(bool, enable_monitor, false, "Enable the system monitor");
+SHELL_FLAG(string, output_format, "table", "Output format for osqueryi");
+CLI_FLAG(uint64, config_refresh, 60, "Seconds between config refreshes");
+HIDDEN_FLAG(bool, debug_internal, false, "Internal debug toggle");
+
+// Read and update flag values at runtime
+std::string val = Flag::getValue("enable_monitor"); // "false"
+Flag::updateValue("enable_monitor", "true");
+
+std::string def;
+Flag::getDefaultValue("config_refresh", def); // def = "60"
+
+bool unchanged = Flag::isDefault("config_refresh"); // true
+bool cliOnly = Flag::isCLIOnlyFlag("config_refresh"); // true
+
+// Print only shell flags (osqueryi --help)
+Flag::printFlags(/*shell=*/true);
```
\ No newline at end of file
diff --git a/osquery/core/.query.md b/osquery/core/.query.md
index 5cfec8773ce..fad25396e46 100644
--- a/osquery/core/.query.md
+++ b/osquery/core/.query.md
@@ -1,60 +1,59 @@
-Defines the `Query` class and `QueryLogItem` struct for managing scheduled query execution history, differential results, and JSON serialization within the osquery framework.
+Defines the `Query` class and `QueryLogItem` struct for managing scheduled query execution history, result diffing, and JSON serialization within the osquery framework.
## Key Components
-### `QueryLogItem` struct
+### `QueryLogItem` (struct)
+Holds metadata and results for a single query execution log entry, supporting both differential and snapshot result modes.
+
| Field | Type | Description |
-|---|---|---|
+|-------|------|-------------|
| `isSnapshot` | `bool` | Flags snapshot vs. differential results |
-| `results` | `DiffResults` | Differential query results |
-| `snapshot_results` | `QueryDataTyped` | Full snapshot results |
-| `name` / `identifier` | `std::string` | Query name and host identifier |
+| `results` | `DiffResults` | Differential result set |
+| `snapshot_results` | `QueryDataTyped` | Full snapshot result set |
| `epoch` / `counter` | `uint64_t` | Execution epoch and invocation counter |
-| `decorations` | `map` | Additional log line metadata |
+| `decorations` | `map` | Extra fields appended to log output |
-### Serialization Functions
-- `serializeQueryLogItem()` β Serializes a `QueryLogItem` into a JSON document
-- `serializeQueryLogItemJSON()` β Serializes a `QueryLogItem` into a JSON string
-- `serializeQueryLogItemAsEvents()` β Serializes as an event-list JSON document
-- `serializeQueryLogItemAsEventsJSON()` β Serializes as a vector of event JSON strings
+### `Query` (class)
+Manages persistent storage and retrieval of scheduled query results via RocksDB.
-### `Query` class
| Method | Description |
-|---|---|
+|--------|-------------|
| `getPreviousQueryResults()` | Loads prior results from RocksDB into a `QueryDataSet` |
-| `saveQueryResults()` | Persists updated results JSON and epoch to the database |
+| `saveQueryResults()` | Persists serialized JSON results and epoch to RocksDB |
| `addNewResults()` | Stores new results and computes differential vs. last run |
| `addNewEvents()` | Variant of `addNewResults` for event-based queries |
| `getQueryCounter()` | Returns/increments the invocation counter, handling resets |
-| `isNewQuerySql()` | Detects if the query SQL has changed since last run |
-| `getStoredQueryNames()` | Static; returns all query names persisted in RocksDB |
+| `isNewQuerySql()` | Detects if the query SQL has been altered since last run |
+| `getStoredQueryNames()` | Static β returns all query names persisted in RocksDB |
+
+### Serialization Functions
+Free functions for converting `QueryLogItem` to JSON:
+- `serializeQueryLogItem()` / `serializeQueryLogItemJSON()` β standard serialization
+- `serializeQueryLogItemAsEvents()` / `serializeQueryLogItemAsEventsJSON()` β event-list form
## Usage Example
```c
-// Initialize and run a scheduled query, capturing differential results
-ScheduledQuery sq;
-sq.query = "SELECT * FROM processes;";
-
-Query q("process_monitor", sq);
+// Construct and execute a query diff cycle
+ScheduledQuery sq{"SELECT * FROM processes", 60, {}};
+Query q("proc_monitor", sq);
+QueryDataTyped new_results = /* run query */;
uint64_t counter = 0;
DiffResults diff;
-QueryDataTyped results = executeQuery(sq.query);
-Status status = q.addNewResults(std::move(results), current_epoch, counter, diff);
+Status s = q.addNewResults(std::move(new_results), current_epoch, counter, diff);
-if (status.ok()) {
+if (s.ok()) {
QueryLogItem item;
- item.name = "process_monitor";
+ item.name = "proc_monitor";
item.results = diff;
item.epoch = current_epoch;
item.counter = counter;
- item.isSnapshot = false;
- std::string json;
- serializeQueryLogItemJSON(item, json);
- logger.log(json);
+ std::string json_out;
+ serializeQueryLogItemJSON(item, json_out);
+ // send json_out to logger
}
```
\ No newline at end of file
diff --git a/osquery/core/.shutdown.md b/osquery/core/.shutdown.md
index 6480b232439..d9c48360938 100644
--- a/osquery/core/.shutdown.md
+++ b/osquery/core/.shutdown.md
@@ -1,47 +1,49 @@
-Declares the osquery shutdown coordination API, providing functions to request, wait for, and inspect application shutdown state across daemon services and threads.
+Declares the osquery shutdown coordination API, providing functions to request, monitor, and wait for graceful application termination across daemon threads and services.
## Key Components
| Function | Description |
-|---|---|
-| `requestShutdown(int, string)` | Primary shutdown trigger; signals all dispatched services to stop gracefully |
-| `waitForShutdown()` | Blocks the calling thread until shutdown is requested |
-| `waitTimeoutOrShutdown(milliseconds)` | Interruptible sleep β returns early if shutdown is requested |
-| `shutdownRequested()` | Non-blocking check for shutdown state (shell/tool use only) |
-| `getShutdownExitCode()` | Retrieves the stored exit code set during shutdown request |
-| `setShutdownExitCode(int)` | Directly sets the exit code without triggering shutdown |
-| `resetShutdown()` | Resets shutdown state to `false`; intended for internal/testing use only |
+|----------|-------------|
+| `requestShutdown(retcode)` | Primary shutdown trigger; signals all dispatched services to stop |
+| `requestShutdown(retcode, system_log)` | Overload that also writes a message to the system log before shutting down |
+| `waitForShutdown()` | Blocks the calling thread until `requestShutdown` is invoked |
+| `waitTimeoutOrShutdown(timeout)` | Blocks until shutdown is requested **or** the given timeout elapses; returns `true` if shutdown was requested |
+| `shutdownRequested()` | Non-blocking check of shutdown state; primarily for shell tools |
+| `getShutdownExitCode()` | Retrieves the exit code set by the last `requestShutdown` call |
+| `setShutdownExitCode(retcode)` | Directly sets the exit code without triggering shutdown |
+| `resetShutdown()` | Resets shutdown state; intended for internal use and testing only |
## Usage Example
```cpp
#include
-// In main thread β block until shutdown is signaled
+// Signal handler or service stop callback
+void onSignal(int sig) {
+ osquery::requestShutdown(EXIT_SUCCESS);
+}
+
+// Main thread β blocks until shutdown is requested
void runDaemon() {
- waitForShutdown();
- // Proceed with cleanup after shutdown is requested
- Initializer::shutdown(getShutdownExitCode());
+ osquery::waitForShutdown();
+ // Perform cleanup after shutdown is signalled
}
-// In a retry loop β sleep interruptibly
+// Retry loop interruptible by shutdown
void enrollWithRetry() {
- while (!shutdownRequested()) {
- bool done = attemptEnrollment();
- if (done) break;
-
- // Wait 30s or abort early if shutdown is requested
- if (waitTimeoutOrShutdown(std::chrono::milliseconds(30000))) {
- break; // Shutdown was requested
- }
+ using namespace std::chrono_literals;
+ bool should_stop = osquery::waitTimeoutOrShutdown(30000ms);
+ if (should_stop) {
+ return; // Shutdown was requested during wait
}
+ // Continue retry logic
}
-// Request shutdown from an error handler
-void onFatalError(const std::string& reason) {
- requestShutdown(EXIT_FAILURE, reason);
+// Unrecoverable error with system log entry
+void onFatalError() {
+ osquery::requestShutdown(EXIT_FAILURE, "Unrecoverable config error");
}
```
-> **Note:** Prefer `requestShutdown()` over direct `exit()` calls to ensure all event threads and Thrift service pools are properly notified before process termination.
\ No newline at end of file
+> **Note:** Prefer `waitForShutdown()` over polling `shutdownRequested()`. Call `waitForShutdown()` before `Initializer::shutdown` in the main thread.
\ No newline at end of file
diff --git a/osquery/core/.system.md b/osquery/core/.system.md
index 50183a002ee..60ef4425bcc 100644
--- a/osquery/core/.system.md
+++ b/osquery/core/.system.md
@@ -1,52 +1,43 @@
-Defines the `Initializer` class and supporting utilities for bootstrapping osquery process lifecycle, identity, and platform setup within the `osquery` namespace.
+Provides the core initialization, lifecycle management, and system identity utilities for osquery processes, defining the `Initializer` class and related helper functions used across daemon, shell, worker, and watcher process types.
## Key Components
-### `Initializer` Class
-The primary entry point for osquery process initialization. Non-copyable, intended for use in `main()`.
-
-| Method | Description |
-|---|---|
-| `Initializer(argc, argv, tool, init_glog)` | Constructor; configures flags, logging, and tool type |
-| `initDaemon()` | Sets up process as an osquery daemon |
-| `initShell()` | Sets up process as an interactive shell |
-| `initWorkerWatcher(name)` | Spawns and monitors child worker processes |
-| `shutdown(retcode)` | Cleanly stops all services and returns exit code |
-| `requestShutdown(retcode)` | Static; requests graceful shutdown |
-| `shutdownNow(retcode)` | Static; immediate exit without dispatcher teardown |
-| `isWorker()` / `isWatcher()` | Static; detects process role via environment |
-
-### UUID & Identity Utilities
-| Function | Description |
-|---|---|
-| `generateNewUUID()` | Generates a random UUID string |
-| `getInstanceUUID(ident)` | Retrieves persistent instance UUID |
-| `getEphemeralUUID(ident)` | Retrieves session-scoped UUID |
-| `getHostUUID(ident)` | Retrieves hardware-based host UUID |
-| `getHostIdentifier()` | Returns configured unique machine identifier |
-| `isPlaceholderHardwareUUID(uuid)` | Detects invalid/placeholder UUIDs |
-
-### Platform & Process Utilities
-- `platformSetup()` / `platformTeardown()` β COM/platform init on Windows
-- `isUserAdmin()` β Checks admin/root privileges
-- `setThreadName(name)` β Names the current thread
-- `getStartTime()` / `setStartTime(st)` β Tracks tool start time
+**`Initializer` class** β Primary entry point for osquery process setup (non-copyable):
+- `Initializer(argc, argv, tool, init_glog)` β Bootstraps process state; call from `main()`
+- `initDaemon()` β Configures process as an osquery daemon with mutex and config validation
+- `initShell()` β Lightweight shell mode initialization
+- `initWorkerWatcher(name)` β Spawns and monitors worker child processes with CPU/memory bounds
+- `start()` β Begins active work after initialization
+- `shutdown(retcode)` β Stops all services/threads cleanly; returns most appropriate exit code
+- `requestShutdown(retcode)` / `shutdownNow(retcode)` β Static shutdown triggers
+- `isWorker()` / `isWatcher()` β Detect current process role via environment variable
+
+**UUID & Identity helpers:**
+- `generateNewUUID()` β Creates a random UUID string
+- `getInstanceUUID()` / `getEphemeralUUID()` / `getHostUUID()` β Scoped UUID getters returning `Status`
+- `getHardwareUUID()` / `getHostIdentifier()` β Machine-level identification
+- `isPlaceholderHardwareUUID(uuid)` β Filters known invalid/placeholder UUIDs
+
+**System utilities:**
+- `isUserAdmin()` β Checks if the process runs with admin privileges
+- `setThreadName(name)` β Platform-aware thread naming
+- `getStartTime()` / `setStartTime(st)` β Tool start timestamp accessors
+- `platformSetup()` / `platformTeardown()` β Platform-specific init/teardown (e.g., COM on Windows)
## Usage Example
-```cpp
-#include
-
+```c
int main(int argc, char* argv[]) {
- osquery::Initializer runner(argc, argv, osquery::ToolType::DAEMON);
+ osquery::Initializer runner(argc, argv, osquery::ToolType::DAEMON);
+
+ runner.initDaemon();
- runner.initDaemon();
- runner.initWorkerWatcher("osqueryd");
+ // Watcher forks workers; only workers return here
+ runner.initWorkerWatcher("osqueryd");
- // Only worker processes return here
- runner.start();
+ runner.start();
- return runner.shutdown(EXIT_SUCCESS);
+ return runner.shutdown(EXIT_SUCCESS);
}
```
\ No newline at end of file
diff --git a/osquery/core/.tables.md b/osquery/core/.tables.md
index 7dabd713bd7..cf1dd80096a 100644
--- a/osquery/core/.tables.md
+++ b/osquery/core/.tables.md
@@ -1,43 +1,34 @@
-Defines the core data structures and type system for osquery's virtual table infrastructure, including SQLite type affinity macros, constraint handling, and table metadata used when implementing and querying osquery tables.
+Defines core data structures and types for osquery's virtual table system, providing the foundational abstractions for SQL query constraint handling, column type affinities, and table attribute management used by all osquery table implementations.
## Key Components
-### Type Affinity Macros
-- `SQL_TEXT(x)`, `INTEGER(x)`, `BIGINT(x)`, `UNSIGNED_BIGINT(x)`, `DOUBLE(x)` β convert native C++ values to SQLite string representations via `__sqliteField()`
-- `TEXT_LITERAL`, `INTEGER_LITERAL`, `BIGINT_LITERAL`, `UNSIGNED_BIGINT_LITERAL`, `DOUBLE_LITERAL` β C++ type aliases for table column literals
-
-### Enumerations
-- `ConstraintOperator` β SQL predicate operators (`EQUALS`, `LESS_THAN`, `GLOB`, `REGEXP`, `IN_OP`, etc.)
-- `TableAttributes` β bitflag enum describing table behavior (`CACHEABLE`, `EVENT_BASED`, `USER_BASED`, `PENDING`, etc.)
-
-### Structs & Classes
-- `Constraint` β pairs a `ConstraintOperator` with a string expression
-- `ConstraintList` β ordered set of `Constraint` objects for a single column; supports `matches()`, `exists()`, `existsAndMatches()`, `notExistsOrMatches()`, and `getAll()`
-
-### Type Aliases
-- `TableColumns` β ordered vector of `(name, ColumnType, ColumnOptions)` tuples
-- `ConstraintMap` β maps column names to their `ConstraintList`
-- `ConstraintSet` β parsed predicate pairs used to populate a `ConstraintMap`
-- `UsedColumns` / `UsedColumnsBitset` β tracks which columns are referenced in a query
+- **`__sqliteField()`** β Overloaded inline helpers that convert various C/C++ types (primitives, char arrays, strings) into `std::string` for SQLite storage
+- **Type Affinity Macros** β `SQL_TEXT`, `INTEGER`, `BIGINT`, `UNSIGNED_BIGINT`, `DOUBLE` for column value conversion; `TEXT_LITERAL`, `INTEGER_LITERAL`, etc. for C++ type aliases
+- **`ConstraintOperator`** β Enum of SQL predicate operators (`EQUALS`, `GREATER_THAN`, `LIKE`, `GLOB`, `REGEXP`, etc.)
+- **`Constraint`** β POD struct pairing an operator with its expression string
+- **`ConstraintList`** β Non-copyable collection of `Constraint` objects for a single column; provides `matches()`, `exists()`, `existsAndMatches()`, `notExistsOrMatches()`, and `getAll()` query helpers
+- **`TableAttributes`** β Bitmask enum flagging table behaviors (`CACHEABLE`, `EVENT_BASED`, `USER_BASED`, `PENDING`, etc.)
+- **Type Aliases** β `TableColumns`, `ConstraintMap`, `ConstraintSet`, `UsedColumns`, `UsedColumnsBitset`, `ColumnAliasSet`, `AliasColumnMap`
## Usage Example
```cpp
-// Check if a constraint exists and matches a value
-ConstraintList cl;
-cl.add(Constraint(EQUALS, "root"));
-
-if (cl.existsAndMatches(std::string("root"))) {
- // Filter results to user "root"
+// Checking constraints in a table generator
+void MyTablePlugin::generate(QueryContext& context) {
+ auto& uid_constraints = context.constraints["uid"];
+
+ // Only filter if a constraint was provided
+ if (uid_constraints.exists(EQUALS)) {
+ for (const auto& uid : uid_constraints.getAll(EQUALS)) {
+ // fetch rows matching uid
+ }
+ }
+
+ // Build a row using type affinity macros
+ Row r;
+ r["uid"] = INTEGER(1000);
+ r["name"] = SQL_TEXT("alice");
+ r["size"] = BIGINT(file_size);
}
-
-// Get all EQUALS expressions for iteration
-for (const auto& expr : cl.getAll(EQUALS)) {
- generateRowsForUser(expr);
-}
-
-// Convert a native value to SQLite text representation
-std::string val = INTEGER(42); // "42"
-std::string txt = SQL_TEXT("hi"); // "hi"
```
\ No newline at end of file
diff --git a/osquery/core/.watcher.md b/osquery/core/.watcher.md
index 93cd774f62e..ed2feeba5cf 100644
--- a/osquery/core/.watcher.md
+++ b/osquery/core/.watcher.md
@@ -1,41 +1,39 @@
-Defines the watchdog infrastructure for osquery, managing the lifecycle and performance monitoring of worker processes and autoloaded extension processes.
+Thread-safe watchdog system for managing and monitoring osquery worker and extension child processes, enforcing CPU, memory, and respawn performance limits.
## Key Components
### Enums & Structs
-- **`WatchdogLimitType`** β Categorizes performance limits: `MEMORY_LIMIT`, `UTILIZATION_LIMIT`, `RESPAWN_LIMIT`, `RESPAWN_DELAY`, `LATENCY_LIMIT`, `INTERVAL`
-- **`PerformanceState`** β Snapshot struct tracking CPU time, memory footprint, respawn timestamps, and sustained latency counters for a monitored process
+- **`WatchdogLimitType`** β Categorizes performance limit types: `MEMORY_LIMIT`, `UTILIZATION_LIMIT`, `RESPAWN_LIMIT`, `RESPAWN_DELAY`, `LATENCY_LIMIT`, `INTERVAL`
+- **`PerformanceState`** β Snapshot struct tracking CPU times, respawn timestamp, sustained latency, and initial memory footprint for a monitored process
+- **`ExtensionMap`** β Alias for `std::map>`
### Classes
-- **`Watcher`** β Thread-safe, noncopyable singleton managing the worker and extension process map. Tracks performance states, restart counts, and process handles. Only accessible by `WatcherRunner`
-- **`WatcherRunner`** β `InternalRunnable` thread that spawns, monitors, and respawns worker/extension processes. Enforces resource limits and handles clean/forced shutdowns
-- **`WatcherWatcherRunner`** β A reverse-watchdog spawned inside the worker process; monitors the parent watcher process and exits if it disappears
+- **`Watcher`** β Non-copyable, thread-safe state manager for the worker process and autoloaded extensions. Tracks performance states, process handles, restart counts, and fate-binding between watcher and worker. Exposes `hasManagedExtensions()`, `loadExtensions()`, and `getWorkerStatus()`
+- **`WatcherRunner`** β `InternalRunnable` dispatcher thread that spawns/monitors worker and extension processes. Polls health, enforces limits, and respawns children that violate thresholds. Key methods: `watch()`, `watchExtensions()`, `isChildSane()`, `isWatcherHealthy()`, `createWorker()`, `createExtension()`, `stopChild()`
+- **`WatcherWatcherRunner`** β `InternalRunnable` spawned inside the worker process to watch the watcher itself, ensuring the worker exits if its parent watchdog dies
### Free Functions
-- **`getWorkerLimit(WatchdogLimitType)`** β Returns a numeric performance threshold for a given limit category and configured watchdog level
-
-### Type Aliases
-
-- **`ExtensionMap`** β `std::map>` mapping extension paths to their process handles
+- **`getWorkerLimit(WatchdogLimitType)`** β Returns the numeric performance limit for a given limit category and configured watchdog level
## Usage Example
```cpp
-// Construct and bind a Watcher, then launch the WatcherRunner thread
+// Instantiate and bind a Watcher
auto watcher = std::make_shared();
watcher->loadExtensions();
+// Spawn the WatcherRunner dispatcher thread
auto runner = std::make_shared(
- argc, argv, /*use_worker=*/true, watcher);
-
-// Query a specific performance limit
-uint64_t memLimit = osquery::getWorkerLimit(
- osquery::WatchdogLimitType::MEMORY_LIMIT);
-
-// Bind watcher/worker fates (watcher exit kills worker)
-watcher->bindFates();
+ argc, argv, /*use_worker=*/true, watcher
+);
+Dispatcher::addService(runner);
+
+// Query a performance limit threshold
+uint64_t mem_limit = osquery::getWorkerLimit(
+ osquery::WatchdogLimitType::MEMORY_LIMIT
+);
```
\ No newline at end of file
diff --git a/osquery/core/plugins/.logger.md b/osquery/core/plugins/.logger.md
index 201e0d11239..951ab08c16f 100644
--- a/osquery/core/plugins/.logger.md
+++ b/osquery/core/plugins/.logger.md
@@ -1,28 +1,26 @@
-Defines the pluggable logging interface for osquery, providing the base class and supporting types for implementing custom log destinations (e.g., Flume, Splunk, syslog).
+Defines the `LoggerPlugin` base class and supporting types for osquery's pluggable logging system, enabling custom log destinations (Splunk, syslog, Flume, etc.) via a plugin interface.
## Key Components
-### Enumerations
-- **`LoggerFeatures`** β Opt-in feature flags: `LOGGER_FEATURE_BLANK`, `LOGGER_FEATURE_LOGSTATUS`, `LOGGER_FEATURE_LOGEVENT`
-- **`StatusLogSeverity`** β Severity levels mirroring Glog: `O_INFO`, `O_WARNING`, `O_ERROR`, `O_FATAL`
-
-### Structs
-- **`StatusLogLine`** β Intermediate log entry holding severity, filename, line number, message, timestamp, UNIX time, and host identifier
-
-### Classes
-- **`LoggerPlugin`** β Abstract base class (extends `Plugin`) for all logger implementations
-
-### `LoggerPlugin` Virtual Methods
-
-| Method | Required | Description |
-|---|---|---|
-| `logString(s)` | β
Pure virtual | Core log output handler |
-| `init(binary_name, log)` | β
Pure virtual | Called once at startup with buffered pre-init logs |
-| `logStatus(log)` | Optional | Handles Glog status lines |
-| `logSnapshot(s)` | Optional | Handles snapshot query results; defaults to `logString` |
-| `logEvent(s)` | Optional | Handles individual forwarded events |
-| `logStringBatch(batch)` | Optional | Handles a JSON array batch of events |
+**Enumerations**
+- `LoggerFeatures` β Feature flags (`LOGGER_FEATURE_BLANK`, `LOGGER_FEATURE_LOGSTATUS`, `LOGGER_FEATURE_LOGEVENT`) for opt-in logger capabilities
+- `StatusLogSeverity` β Severity levels (`O_INFO`, `O_WARNING`, `O_ERROR`, `O_FATAL`) mapped to Glog's `LogSeverity`
+
+**Structs**
+- `StatusLogLine` β Intermediate log record holding `severity`, `filename`, `line`, `message`, `calendar_time`, `time`, and `identifier`
+
+**Class: `LoggerPlugin`** *(extends `Plugin`)*
+| Method | Description |
+|--------|-------------|
+| `logString(s)` | **Pure virtual.** Core logging method all subclasses must implement |
+| `init(binary_name, log)` | **Pure virtual.** Called once on startup with buffered pre-init logs |
+| `logStatus(log)` | Optional. Handle Glog status lines directly |
+| `logSnapshot(s)` | Optional. Separate sink for snapshot query results; defaults to `logString` |
+| `logEvent(s)` | Optional. Per-event forwarding, bypassing the database layer |
+| `logStringBatch(batch)` | Optional. Batch event processing; iterates JSON array calling `logString` |
+| `usesLogStatus()` | Feature flag; return `true` to intercept Glog output |
+| `usesLogEvent()` | Feature flag; return `true` to receive direct event forwarding |
## Usage Example
@@ -32,25 +30,17 @@ Defines the pluggable logging interface for osquery, providing the base class an
class MyLoggerPlugin : public osquery::LoggerPlugin {
public:
osquery::Status logString(const std::string& s) override {
- writeToMyBackend(s);
- return osquery::Status::success();
- }
-
- bool usesLogStatus() override { return true; }
-
- osquery::Status logStatus(
- const std::vector& log) override {
- for (const auto& line : log) {
- writeStatusToMyBackend(line.severity, line.message);
- }
+ sendToMyBackend(s);
return osquery::Status::success();
}
protected:
void init(const std::string& binary_name,
const std::vector& log) override {
- setProcessName(binary_name);
- logStatus(log); // flush buffered pre-init logs
+ // Flush buffered pre-init status logs
+ for (const auto& entry : log) {
+ sendToMyBackend(entry.message);
+ }
}
};
diff --git a/osquery/core/plugins/.plugin.md b/osquery/core/plugins/.plugin.md
index 57a9afb5479..9fe6e1b47f0 100644
--- a/osquery/core/plugins/.plugin.md
+++ b/osquery/core/plugins/.plugin.md
@@ -1,57 +1,50 @@
-Defines the core `Plugin` base class and associated types for the osquery plugin/registry system, providing the interface that all registry items must implement.
+Header defining the core plugin interface and type aliases for osquery's registry-based plugin system.
## Key Components
-| Symbol | Type | Description |
-|--------|------|-------------|
-| `PluginRequest` | `std::map` | Key-value input map passed to a plugin call, typically includes an `"action"` key |
-| `PluginResponse` | `std::vector` | Vector of key-value maps returned from a successful plugin call |
-| `Plugin` | Abstract class | Non-copyable base class all plugins must inherit; requires `call()` implementation |
-| `PluginRef` | `std::shared_ptr` | Shared pointer alias for registry-managed plugin instances |
-| `tableRowsToPluginResponse()` | Free function | Converts a `TableRows` result into a `PluginResponse` |
+- **`PluginRequest`** β Type alias for `std::map`; carries action keys and parameters into a plugin call
+- **`PluginResponse`** β Type alias for `std::vector`; carries structured results back from a plugin call
+- **`Plugin`** β Abstract base class (non-copyable) that all registry plugins must inherit from
+- **`PluginRef`** β Convenience alias for `std::shared_ptr`
+- **`tableRowsToPluginResponse()`** β Free function to convert `TableRows` query results into a `PluginResponse`
-### `Plugin` Virtual Methods
+### `Plugin` Virtual Interface
| Method | Required | Description |
|--------|----------|-------------|
-| `call()` | β
Pure virtual | Handles plugin invocation with request/response |
-| `setUp()` | β Optional | One-time initialization logic |
-| `tearDown()` | β Optional | Cleanup/release logic |
-| `configure()` | β Optional | React to configuration changes |
-| `routeInfo()` | β Optional | Publish additional routing metadata |
-| `addExternal()` | β Static | Hook for when an external plugin is registered |
-| `removeExternal()` | β Static | Hook for when an external plugin is removed |
+| `call()` | β
Pure virtual | Core dispatch method; handles a `PluginRequest` and fills a `PluginResponse` |
+| `setUp()` | Optional | One-time initialization on plugin load |
+| `tearDown()` | Optional | Cleanup on plugin unload |
+| `configure()` | Optional | React to configuration changes |
+| `routeInfo()` | Optional | Publish extra routing metadata |
+| `addExternal()` | Static | Hook for when an external (extension) plugin is registered |
+| `removeExternal()` | Static | Hook for when an external plugin is removed |
## Usage Example
```cpp
#include
-namespace osquery {
-
-class MyPlugin : public Plugin {
+class MyPlugin : public osquery::Plugin {
public:
- Status call(const PluginRequest& request,
- PluginResponse& response) override {
+ osquery::Status call(const osquery::PluginRequest& request,
+ osquery::PluginResponse& response) override {
auto action = request.find("action");
if (action == request.end()) {
- return Status::failure("Missing action key");
+ return osquery::Status::failure("No action specified");
}
if (action->second == "query") {
- response.push_back({{"result", "hello from MyPlugin"}});
- return Status::success();
+ response.push_back({{"result", "some_value"}});
}
- return Status::failure("Unknown action: " + action->second);
+ return osquery::Status::success();
}
- Status setUp() override {
- // Optional: initialize resources
- return Status::success();
+ osquery::Status setUp() override {
+ // Optional one-time init
+ return osquery::Status::success();
}
};
-
-} // namespace osquery
```
\ No newline at end of file
diff --git a/osquery/core/plugins/.sql.md b/osquery/core/plugins/.sql.md
index c0e5554f802..13727b31bfa 100644
--- a/osquery/core/plugins/.sql.md
+++ b/osquery/core/plugins/.sql.md
@@ -1,49 +1,42 @@
-Defines the abstract `SQLPlugin` interface that enables osquery's pluggable SQL execution layer, decoupling the SQL API from its underlying implementation (e.g., SQLite).
+Defines the abstract `SQLPlugin` interface for osquery's pluggable SQL backend, allowing the SQL implementation (e.g., SQLite) to be registered and swapped via the osquery plugin registry without coupling core SDK code to third-party dependencies.
## Key Components
-- **`SQLPlugin`** β Abstract base class inheriting from `Plugin` that defines the contract for SQL backend implementations registered under the `"sql"` registry key.
-
-| Method | Description |
-|---|---|
-| `query()` | Executes a SQL query string and populates a `QueryData` result set |
-| `getQueryColumns()` | Parses a query and returns column metadata (`name`, `type`) |
-| `getQueryTables()` | Returns the list of virtual tables scanned by a given query |
-| `attach()` | Optionally attaches a virtual table at runtime (no-op default) |
-| `detach()` | Optionally detaches a virtual table by name (no-op default) |
-| `call()` | Dispatches plugin registry requests to the appropriate method |
+- **`SQLPlugin`** β Abstract plugin class inheriting from `Plugin` that defines the contract for SQL backend implementations:
+ - `query()` β Executes a SQL query string, returning results in a `QueryData` object
+ - `getQueryColumns()` β Parses a query and returns column metadata (`name`, `type`) as `TableColumns`
+ - `getQueryTables()` β Extracts the list of scanned table names from a query
+ - `attach()` β Virtual hook to attach a named virtual table at runtime (default: no-op success)
+ - `detach()` β Virtual hook to detach a named virtual table (default: no-op success)
+ - `call()` β Overrides the base `Plugin::call()` to handle `PluginRequest`/`PluginResponse` dispatch
## Usage Example
```cpp
#include
-// Implementing a custom SQL backend plugin
class MySQLPlugin : public osquery::SQLPlugin {
public:
osquery::Status query(const std::string& q,
osquery::QueryData& results,
bool use_cache) const override {
- // Execute query against your SQL backend
+ // Execute query against custom SQL backend
return osquery::Status::success();
}
osquery::Status getQueryColumns(const std::string& q,
- osquery::TableColumns& columns) const override {
- // Parse and return column descriptors
+ osquery::TableColumns& cols) const override {
+ // Parse and return column metadata
return osquery::Status::success();
}
osquery::Status getQueryTables(const std::string& q,
std::vector& tables) const override {
- // Return scanned table names
+ // Extract referenced table names
return osquery::Status::success();
}
};
-// Register the plugin under the "sql" registry
REGISTER(MySQLPlugin, "sql", "sql");
-```
-
-> **Note:** The default `attach()` and `detach()` implementations return `Status::success()` β override them only if your backend requires runtime virtual table management (as SQLite does during initialization).
\ No newline at end of file
+```
\ No newline at end of file
diff --git a/osquery/core/sql/.column.md b/osquery/core/sql/.column.md
index 997711a199b..38955890acc 100644
--- a/osquery/core/sql/.column.md
+++ b/osquery/core/sql/.column.md
@@ -1,45 +1,40 @@
-Defines column metadata types and enumerations used to describe osquery table schema β column options, column types, and related type aliases for table definitions.
+Defines column metadata types used by osquery's table plugin system, including column options (flags), column types, and related type aliases for describing table schema.
## Key Components
-### `ColumnOptions` (enum class)
-Bitmask flags controlling column behavior in SQLite table implementations:
+- **`ColumnOptions`** β Bitmask enum controlling column behavior:
+ - `DEFAULT`, `INDEX`, `REQUIRED`, `ADDITIONAL`, `OPTIMIZED`, `HIDDEN`
+ - Collation options: `COLLATEBINARY`, `COLLATENOCASE`, `COLLATERTRIM`, `COLLATEVERSION`, `COLLATEVERSION_ARCH`, `COLLATEVERSION_DPKG`, `COLLATEVERSION_RHEL`
-| Flag | Value | Description |
-|------|-------|-------------|
-| `DEFAULT` | 0 | No special behavior |
-| `INDEX` | 1 | Treat as primary key |
-| `REQUIRED` | 2 | Must appear in query predicate |
-| `ADDITIONAL` | 4 | Generates extra data when in predicate |
-| `OPTIMIZED` | 8 | Enables query-time optimization |
-| `HIDDEN` | 16 | Excluded from `SELECT *` results |
-| `COLLATEBINARY` / `COLLATE*` | 32β2048 | SQLite collation sequences |
+- **`operator|` / `operator&`** β Bitwise operators enabling `ColumnOptions` to be combined and tested as flags.
-Bitwise `|` and `&` operators are overloaded for flag composition.
+- **`ColumnType`** β Enum of supported SQLite column types: `TEXT_TYPE`, `INTEGER_TYPE`, `BIGINT_TYPE`, `UNSIGNED_BIGINT_TYPE`, `DOUBLE_TYPE`, `BLOB_TYPE`.
-### `ColumnType` (enum)
-Supported SQLite column data types: `TEXT_TYPE`, `INTEGER_TYPE`, `BIGINT_TYPE`, `UNSIGNED_BIGINT_TYPE`, `DOUBLE_TYPE`, `BLOB_TYPE`, `UNKNOWN_TYPE`.
+- **`kColumnTypeNames`** β External map from `ColumnType` to its SQLite string representation (e.g., `TEXT_TYPE` β `"TEXT"`).
-### Type Aliases
-- `TableName` β `std::string` alias for plugin/table names
-- `TableColumns` β ordered vector of `(name, ColumnType, ColumnOptions)` tuples describing a table's schema
-- `ColumnAliasSet` β map of column name to a set of alias strings
+- **`TableColumns`** β Ordered vector of tuples `(column_name, ColumnType, ColumnOptions)` describing a table's schema.
-### `kColumnTypeNames`
-External map from `ColumnType` to its SQLite string representation (e.g., `TEXT`, `INTEGER`).
+- **`ColumnAliasSet`** β Map of column names to their alias sets.
## Usage Example
-```cpp
-#include
+```c
#include "column.h"
-osquery::TableColumns myTableColumns = {
- // Column name, type, options
- {"uid", osquery::INTEGER_TYPE, osquery::ColumnOptions::INDEX},
- {"name", osquery::TEXT_TYPE, osquery::ColumnOptions::DEFAULT},
- {"token", osquery::TEXT_TYPE, osquery::ColumnOptions::HIDDEN |
- osquery::ColumnOptions::REQUIRED},
+using namespace osquery;
+
+// Define a table's columns with types and options
+TableColumns myTableColumns = {
+ {"pid", INTEGER_TYPE, ColumnOptions::INDEX},
+ {"name", TEXT_TYPE, ColumnOptions::DEFAULT},
+ {"uid", BIGINT_TYPE, ColumnOptions::ADDITIONAL | ColumnOptions::HIDDEN},
+ {"version", TEXT_TYPE, ColumnOptions::OPTIMIZED | ColumnOptions::COLLATEVERSION},
};
+
+// Test a column option flag
+ColumnOptions opts = ColumnOptions::INDEX | ColumnOptions::REQUIRED;
+if (opts & ColumnOptions::REQUIRED) {
+ // Column requires a WHERE predicate
+}
```
\ No newline at end of file
diff --git a/osquery/core/sql/.diff_results.md b/osquery/core/sql/.diff_results.md
index fdf548bc014..51af93279fa 100644
--- a/osquery/core/sql/.diff_results.md
+++ b/osquery/core/sql/.diff_results.md
@@ -1,44 +1,44 @@
-Defines the `DiffResults` structure and related utilities for computing and serializing the difference between two query result sets in osquery.
+Defines the `DiffResults` structure and related utilities for computing and serializing the difference between two osquery query result sets.
## Key Components
### `DiffResults` (struct)
-A move-only struct representing the delta between two `QueryDataTyped` result sets:
+A move-only struct holding the delta between two `QueryDataTyped` result sets.
| Member | Type | Description |
-|---|---|---|
+|--------|------|-------------|
| `added` | `QueryDataTyped` | Rows present in the new result but not the old |
| `removed` | `QueryDataTyped` | Rows present in the old result but not the new |
-
-**Methods:**
-- `hasNoResults()` β Returns `true` if both `added` and `removed` are empty
-- `operator==` / `operator!=` β Equality comparison between two `DiffResults`
+| `hasNoResults()` | `bool` | Returns `true` if both `added` and `removed` are empty |
+| `operator==` / `operator!=` | `bool` | Value-equality comparisons |
### Free Functions
-| Function | Description |
-|---|---|
-| `diff(old_, new_)` | Computes delta between a `QueryDataSet` and `QueryDataTyped`, returns a `DiffResults` |
-| `serializeDiffResults(...)` | Serializes a `DiffResults` into a `rapidjson::Document` object |
-| `serializeDiffResultsJSON(...)` | Serializes a `DiffResults` into a JSON string |
+| Function | Returns | Description |
+|----------|---------|-------------|
+| `diff(old_, new_)` | `DiffResults` | Computes the delta between a `QueryDataSet` and a `QueryDataTyped` |
+| `serializeDiffResults(d, doc, obj, asNumeric)` | `Status` | Serializes into a `rapidjson::Document` object with `added`/`removed` keys |
+| `serializeDiffResultsJSON(d, json, asNumeric)` | `Status` | Serializes into a JSON string |
## Usage Example
```cpp
-// Compute diff between old and new query results
-QueryDataSet oldResults = getStoredResults();
-QueryDataTyped newResults = runQuery();
+#include
-DiffResults delta = osquery::diff(oldResults, newResults);
+// Compute diff between previous and current query results
+QueryDataSet previous = getPreviousResults();
+QueryDataTyped current = getCurrentResults();
-if (!delta.hasNoResults()) {
- std::string jsonOutput;
- auto status = osquery::serializeDiffResultsJSON(delta, jsonOutput, false);
+DiffResults delta = osquery::diff(previous, current);
+if (!delta.hasNoResults()) {
+ std::string json;
+ auto status = osquery::serializeDiffResultsJSON(delta, json, /*asNumeric=*/false);
if (status.ok()) {
- // jsonOutput contains {"added": [...], "removed": [...]}
- processChanges(jsonOutput);
+ processChanges(json); // { "added": [...], "removed": [...] }
}
}
-```
\ No newline at end of file
+```
+
+> **Note:** `DiffResults` is move-only (`only_movable`). Use `std::move` when passing instances between scopes β copy construction and assignment are disabled.
\ No newline at end of file
diff --git a/osquery/core/sql/.query_data.md b/osquery/core/sql/.query_data.md
index 554cf1f10c3..4975f3cbc7c 100644
--- a/osquery/core/sql/.query_data.md
+++ b/osquery/core/sql/.query_data.md
@@ -1,25 +1,23 @@
-Defines the core result set types and serialization utilities for osquery SQL query results, providing `QueryData`, `QueryDataTyped`, and `QueryDataSet` container types along with JSON serialization/deserialization functions.
+Defines the core result set types and serialization utilities for osquery SQL query results, providing `QueryData`, `QueryDataTyped`, and `QueryDataSet` containers along with JSON conversion functions.
## Key Components
-### Type Aliases
-| Type | Definition | Purpose |
-|---|---|---|
-| `QueryData` | `std::vector` | Standard untyped SQL result set |
-| `QueryDataTyped` | `std::vector` | Typed SQL result set |
-| `QueryDataSet` | `std::multiset` | Multiset for fast row lookup |
+**Type Aliases**
+- `QueryData` β `std::vector`; the standard untyped SQL result set
+- `QueryDataTyped` β `std::vector`; typed SQL result set
+- `QueryDataSet` β `std::multiset`; set-based result for fast row lookup
-### Serialization Functions
-- **`serializeQueryData`** β Converts `QueryData` or `QueryDataTyped` into a RapidJSON array, with optional numeric value preservation
-- **`serializeQueryDataJSON`** β Serializes query results directly to a `JSON` document or `std::string`
+**Serialization**
+- `serializeQueryData()` β Serializes `QueryData` or `QueryDataTyped` into a `rapidjson::Document` array; typed variant accepts an `asNumeric` flag to preserve numeric types
+- `serializeQueryDataJSON()` β Convenience overloads serializing directly to a `JSON` document or `std::string`
-### Deserialization Functions
-- **`deserializeQueryData`** β Overloaded for `QueryData`, `QueryDataTyped`, and `QueryDataSet` targets from a `rapidjson::Value`
-- **`deserializeQueryDataJSON`** β Overloaded for `QueryData` and `QueryDataSet` targets from a JSON string or `JSON` document
+**Deserialization**
+- `deserializeQueryData()` β Converts a `rapidjson::Value` array back into `QueryData`, `QueryDataTyped`, or `QueryDataSet`
+- `deserializeQueryDataJSON()` β Converts a `JSON` doc or JSON string back into `QueryData` or `QueryDataSet`
-### Utility
-- **`addUniqueRowToQueryData`** β Appends a `RowTyped` to a `QueryDataTyped` only if it does not already exist (linear scan)
+**Utilities**
+- `addUniqueRowToQueryData()` β Appends a `RowTyped` to a `QueryDataTyped` only if it is not already present (linear scan)
## Usage Example
@@ -27,21 +25,20 @@ Defines the core result set types and serialization utilities for osquery SQL qu
#include
// Serialize query results to JSON string
-osquery::QueryData results = runMyQuery();
-std::string jsonOutput;
-auto status = osquery::serializeQueryDataJSON(results, jsonOutput);
-if (!status.ok()) {
- LOG(ERROR) << "Serialization failed: " << status.getMessage();
+osquery::QueryData results = runSomeQuery();
+std::string json;
+auto status = osquery::serializeQueryDataJSON(results, json);
+if (status.ok()) {
+ LOG(INFO) << "Results: " << json;
}
// Deserialize back from JSON
osquery::QueryData restored;
-status = osquery::deserializeQueryDataJSON(jsonOutput, restored);
-
-// Add unique rows only
-osquery::QueryDataTyped typedResults;
-osquery::RowTyped row = buildRow();
-bool added = osquery::addUniqueRowToQueryData(typedResults, row);
-```
-
-> **Note:** `addUniqueRowToQueryData` performs a linear scan β avoid using it in performance-critical loops with large result sets.
\ No newline at end of file
+osquery::deserializeQueryDataJSON(json, restored);
+
+// Append unique typed rows
+osquery::QueryDataTyped typed;
+osquery::RowTyped row = {{"column", {1LL}}};
+osquery::addUniqueRowToQueryData(typed, row); // added
+osquery::addUniqueRowToQueryData(typed, row); // skipped (duplicate)
+```
\ No newline at end of file
diff --git a/osquery/core/sql/.query_performance.md b/osquery/core/sql/.query_performance.md
index 2441d260de2..40a0516c480 100644
--- a/osquery/core/sql/.query_performance.md
+++ b/osquery/core/sql/.query_performance.md
@@ -1,45 +1,49 @@
-Defines the `QueryPerformance` struct within the `osquery` namespace for tracking runtime performance statistics of scheduled queries.
+Defines the `QueryPerformance` struct within the `osquery` namespace for tracking per-query execution statistics, including timing, memory, and output metrics.
## Key Components
### `QueryPerformance` (struct)
-Aggregates cumulative and per-execution metrics for a single query:
+Aggregates performance data collected across query executions:
| Field | Type | Description |
-|---|---|---|
+|-------|------|-------------|
| `executions` | `size_t` | Total number of times the query has run |
-| `last_executed` | `uint64_t` | UNIX timestamp (seconds) of last successful execution |
-| `wall_time` / `wall_time_ms` | `uint64_t` | Cumulative wall clock time (seconds / milliseconds) |
+| `last_executed` | `uint64_t` | Last successful execution timestamp (UNIX seconds) |
+| `wall_time` / `wall_time_ms` | `uint64_t` | Cumulative wall time (seconds / milliseconds) |
| `last_wall_time_ms` | `uint64_t` | Wall time of the most recent execution (ms) |
-| `user_time` / `last_user_time` | `uint64_t` | Cumulative and latest user-space CPU time (ms) |
-| `system_time` / `last_system_time` | `uint64_t` | Cumulative and latest kernel CPU time (ms) |
-| `average_memory` | `uint64_t` | Average resident memory (bytes) after result collection |
-| `last_memory` | `uint64_t` | Resident memory of the most recent execution (bytes) |
+| `user_time` / `last_user_time` | `uint64_t` | Cumulative and latest user-mode CPU time (ms) |
+| `system_time` / `last_system_time` | `uint64_t` | Cumulative and latest kernel-mode CPU time (ms) |
+| `average_memory` | `uint64_t` | Average resident memory after result collection (bytes) |
+| `last_memory` | `uint64_t` | Resident memory after the latest execution (bytes) |
| `output_size` | `uint64_t` | Total bytes produced by the query |
**Methods:**
-- `QueryPerformance(const std::string& csv)` β Deserializes a `QueryPerformance` from a CSV string
-- `toCSV() const` β Serializes the struct to a CSV string for persistence
-- `operator==` β Equality comparison between two instances
+- `QueryPerformance(const std::string& csv)` β Constructs an instance by deserializing a CSV string
+- `toCSV() const` β Serializes the struct to a CSV string for storage or transport
+- `operator==` β Equality comparison between two `QueryPerformance` instances
## Usage Example
```cpp
#include "query_performance.h"
-// Default-initialize and inspect after a query run
+// Default construction
osquery::QueryPerformance perf;
-perf.executions++;
-perf.last_wall_time_ms = 42;
+perf.executions = 1;
+perf.wall_time_ms = 42;
+perf.last_memory = 204800;
-// Persist to CSV
-std::string serialized = perf.toCSV();
+// Serialize to CSV for persistence
+std::string csv = perf.toCSV();
// Restore from CSV
-osquery::QueryPerformance restored(serialized);
+osquery::QueryPerformance restored(csv);
-assert(perf == restored);
+// Compare
+if (perf == restored) {
+ // Serialization round-trip succeeded
+}
```
\ No newline at end of file
diff --git a/osquery/core/sql/.row.md b/osquery/core/sql/.row.md
index e0e3d010bcc..7fecf377044 100644
--- a/osquery/core/sql/.row.md
+++ b/osquery/core/sql/.row.md
@@ -1,27 +1,24 @@
-Defines the core data types and serialization utilities for representing single database query rows in osquery, supporting both string-based and typed (SQLite affinity) row formats.
+Defines the core data structures and serialization utilities for representing and manipulating single database query rows within the osquery framework.
## Key Components
### Type Aliases
-
| Type | Definition |
-|------|-----------|
+|------|------------|
| `RowData` | `std::string` β raw column value |
| `RowDataTyped` | `boost::variant` β typed column value |
-| `Row` | `std::map` β untyped string row |
-| `RowTyped` | `std::map` β typed variant row |
+| `Row` | `std::map` β untyped row (column β string) |
+| `RowTyped` | `std::map` β typed row (column β variant) |
| `ColumnNames` | `std::vector` β ordered column name list |
### Serialization Functions
-
-- **`serializeRow`** β Serializes a `Row` or `RowTyped` into a `rapidjson::Value` object, with optional column ordering via `ColumnNames`
-- **`serializeRowJSON`** β Serializes a `Row` or `RowTyped` directly to a JSON string; typed variant accepts an `asNumeric` flag to preserve numeric types
+- **`serializeRow`** β Serializes a `Row` or `RowTyped` into a `rapidjson::Value` object within a managed `JSON` document
+- **`serializeRowJSON`** β Serializes a `Row` or `RowTyped` directly to a JSON string; supports optional numeric type preservation via `asNumeric`
### Deserialization Functions
-
- **`deserializeRow`** β Deserializes a `rapidjson::Value` object into a `Row` or `RowTyped`
-- **`deserializeRowJSON`** β Deserializes a JSON string into a `Row` or `RowTyped`
+- **`deserializeRowJSON`** β Deserializes a raw JSON string into a `Row` or `RowTyped`
All functions return an osquery `Status` object indicating success or failure.
@@ -29,29 +26,30 @@ All functions return an osquery `Status` object indicating success or failure.
```c
#include
-#include
+#include
-// Serialize a Row to JSON string
+// Build a simple row
osquery::Row r;
-r["pid"] = "1234";
+r["pid"] = "1234";
r["name"] = "my_process";
-std::string json_output;
-auto status = osquery::serializeRowJSON(r, json_output);
+// Serialize to JSON string
+std::string json;
+auto status = osquery::serializeRowJSON(r, json);
if (status.ok()) {
- // json_output -> {"pid":"1234","name":"my_process"}
+ // json == {"pid":"1234","name":"my_process"}
}
-// Deserialize back from JSON string
-osquery::Row restored;
-osquery::deserializeRowJSON(json_output, restored);
+// Deserialize back from JSON
+osquery::Row r2;
+osquery::deserializeRowJSON(json, r2);
-// Using typed rows with numeric preservation
-osquery::RowTyped typed_row;
-typed_row["pid"] = (long long)1234;
-typed_row["load"] = 0.75;
+// Typed row with numeric preservation
+osquery::RowTyped rt;
+rt["pid"] = 1234LL;
+rt["load"] = 0.75;
+rt["name"] = std::string("my_process");
-std::string typed_json;
-osquery::serializeRowJSON(typed_row, typed_json, /*asNumeric=*/true);
-// typed_json -> {"pid":1234,"load":0.75}
+std::string typedJson;
+osquery::serializeRowJSON(rt, typedJson, /*asNumeric=*/true);
```
\ No newline at end of file
diff --git a/osquery/core/sql/.scheduled_query.md b/osquery/core/sql/.scheduled_query.md
index 42d5c135e19..c9dfaf24754 100644
--- a/osquery/core/sql/.scheduled_query.md
+++ b/osquery/core/sql/.scheduled_query.md
@@ -1,48 +1,49 @@
-Defines the `ScheduledQuery` struct used within osqueryd to represent all relevant parameters and metadata for a scheduled SQL query.
+Defines the `ScheduledQuery` struct representing a single scheduled query's configuration within the osqueryd daemon.
## Key Components
### `ScheduledQuery` (struct)
-A move-only data structure (inherits `only_movable`) containing:
+A move-only data structure (inherits `only_movable`) encapsulating all attributes of a scheduled query:
| Field | Type | Description |
|---|---|---|
| `pack_name` | `std::string` | Name of the containing pack |
| `name` | `std::string` | Query identifier |
-| `query` | `std::string` | Raw SQL query string |
-| `oncall` | `std::string` | Query owner/team |
+| `query` | `std::string` | SQL statement |
+| `oncall` | `std::string` | Query owner |
| `interval` | `uint64_t` | Execution frequency in seconds |
-| `splayed_interval` | `uint64_t` | Temporary splayed interval value |
-| `startup_priority` | `uint64_t` | Startup execution priority (`UINT64_MAX` = disabled) |
-| `denylisted` | `bool` | Whether query is currently denylisted |
-| `options` | `std::map` | Key/value query option flags |
+| `splayed_interval` | `uint64_t` | Temporary splayed interval |
+| `startup_priority` | `uint64_t` | Startup run priority (`UINT64_MAX` = disabled) |
+| `denylisted` | `bool` | Whether query is denylisted |
+| `options` | `map` | Key-value query options (e.g. `snapshot`, `removed`) |
-**Methods:**
-- `isSnapshotQuery()` β Returns `true` if the `"snapshot"` option is set
-- `reportRemovedRows()` β Returns `true` if the `"removed"` option is set or absent (default behavior)
-- `operator==` / `operator!=` β Equality based on `query` and `interval` fields
+### Key Methods
+
+- **`isSnapshotQuery()`** β Returns `true` if the `snapshot` option is set to `true`
+- **`reportRemovedRows()`** β Returns `true` if the `removed` option is set or absent (default behavior)
+- **`operator==` / `operator!=`** β Equality based on `query` and `interval` fields only
## Usage Example
```cpp
#include
-// Construct with required fields
-osquery::ScheduledQuery sq("my_pack", "active_users", "SELECT * FROM users;");
+// Construct a scheduled query
+osquery::ScheduledQuery sq("my_pack", "running_procs", "SELECT * FROM processes;");
sq.interval = 60;
sq.options["snapshot"] = false;
sq.options["removed"] = true;
-// Check query behavior
+// Inspect query behavior
if (sq.isSnapshotQuery()) {
- // handle snapshot mode
+ // handle snapshot mode
}
if (sq.reportRemovedRows()) {
- // include removed row diffs in results
+ // emit removed row events
}
-// Move semantics only β copies are disabled
+// Move semantics only β copy is disabled
osquery::ScheduledQuery sq2 = std::move(sq);
```
\ No newline at end of file
diff --git a/osquery/core/sql/.table_rows.md b/osquery/core/sql/.table_rows.md
index 91963c102ad..f7211a7c353 100644
--- a/osquery/core/sql/.table_rows.md
+++ b/osquery/core/sql/.table_rows.md
@@ -3,45 +3,33 @@ Defines the `TableRows` type alias and declares serialization/deserialization ut
## Key Components
-| Symbol | Type | Description |
-|---|---|---|
-| `TableRows` | Type alias | `std::vector` β an ordered collection of table row objects |
-| `serializeTableRows` | Function | Serializes a `TableRows` into a `rapidjson::Document` JSON array |
-| `serializeTableRowsJSON` | Function | Serializes a `TableRows` directly into a JSON string |
-| `deserializeTableRows` | Function | Converts a `rapidjson::Value` JSON array back into a `TableRows` |
-| `deserializeTableRowsJSON` | Function | Converts a raw JSON string back into a `TableRows` |
-
-All functions return `osquery::Status` to indicate success or failure.
+- **`TableRows`** β Type alias for `std::vector`, representing a collection of query result rows.
+- **`serializeTableRows()`** β Serializes a `TableRows` object into a `rapidjson::Document` JSON array.
+- **`serializeTableRowsJSON()`** β Serializes a `TableRows` object directly into a JSON-formatted `std::string`.
+- **`deserializeTableRows()`** β Converts a `rapidjson::Value` JSON array back into a `TableRows` object.
+- **`deserializeTableRowsJSON()`** β Converts a raw JSON string back into a `TableRows` object.
## Usage Example
```c
#include "table_rows.h"
-// Serialize to JSON string
-osquery::TableRows rows = getMyTableRows();
-std::string jsonOutput;
+osquery::TableRows rows;
+// ... populate rows from a query ...
-osquery::Status s = osquery::serializeTableRowsJSON(rows, jsonOutput);
-if (!s.ok()) {
- LOG(ERROR) << "Serialization failed: " << s.getMessage();
+// Serialize to JSON string
+std::string json_output;
+osquery::Status status = osquery::serializeTableRowsJSON(rows, json_output);
+if (status.ok()) {
+ // json_output now contains the serialized rows
}
-// Deserialize from JSON string
-osquery::TableRows restored;
-osquery::Status ds = osquery::deserializeTableRowsJSON(jsonOutput, restored);
+// Deserialize back from JSON string
+osquery::TableRows restored_rows;
+osquery::Status ds = osquery::deserializeTableRowsJSON(json_output, restored_rows);
if (!ds.ok()) {
- LOG(ERROR) << "Deserialization failed: " << ds.getMessage();
+ // handle error
}
-
-// Serialize into an existing JSON document/array
-osquery::JSON doc;
-rapidjson::Document arr;
-osquery::serializeTableRows(rows, doc, arr);
```
-## Dependencies
-
-- `osquery/utils/json/json.h` β JSON document wrapper
-- `query_data.h` β underlying query result types
-- `table_row.h` β `TableRowHolder` definition
\ No newline at end of file
+All four functions return an `osquery::Status` object β check `.ok()` to confirm success or retrieve an error message via `.getMessage()`.
\ No newline at end of file
diff --git a/osquery/core/windows/.global_users_groups_cache.md b/osquery/core/windows/.global_users_groups_cache.md
index 42bc31f30e6..67f5427aa59 100644
--- a/osquery/core/windows/.global_users_groups_cache.md
+++ b/osquery/core/windows/.global_users_groups_cache.md
@@ -1,34 +1,31 @@
-Declares the `GlobalUsersGroupsCache` class, which provides synchronized global access to Windows user and group cache data initialized by background services.
+Provides a thread-safe global accessor for Windows user and group caches, blocking until the respective cache has been initialized by its background service before returning a reference.
## Key Components
-### `GlobalUsersGroupsCache` (class)
-
-A singleton-style accessor class for Windows users and groups cache data, designed to block until cache initialization completes before returning references.
+**`GlobalUsersGroupsCache`** β Singleton-style class exposing two static accessors backed by `std::shared_future` synchronization.
| Member | Type | Description |
|--------|------|-------------|
| `getUsersCache()` | `static const UsersCache&` | Blocks until the users cache is ready, then returns a const reference |
| `getGroupsCache()` | `static const GroupsCache&` | Blocks until the groups cache is ready, then returns a const reference |
-| `global_users_cache_future_` | `std::shared_future` | Synchronization primitive tracking users cache initialization |
-| `global_groups_cache_future_` | `std::shared_future` | Synchronization primitive tracking groups cache initialization |
-| `global_users_cache_` | `std::shared_ptr` | Shared ownership pointer to the users cache instance |
-| `global_groups_cache_` | `std::shared_ptr` | Shared ownership pointer to the groups cache instance |
+| `global_users_cache_future_` | `std::shared_future` | Signals when the users cache has finished initialization |
+| `global_groups_cache_future_` | `std::shared_future` | Signals when the groups cache has finished initialization |
+| `global_users_cache_` | `std::shared_ptr` | Owned users cache instance |
+| `global_groups_cache_` | `std::shared_ptr` | Owned groups cache instance |
-**Friend declarations:** `Initializer`, `initUsersAndGroupsServices`, `deinitUsersAndGroupsServices` β only these can populate the private cache state.
+**Friend declarations** grant `Initializer`, `initUsersAndGroupsServices`, and `deinitUsersAndGroupsServices` access to private members for lifecycle management.
## Usage Example
```cpp
#include
-// Blocks until the background service has finished populating the cache,
-// then returns a safe const reference for querying.
+// Safely retrieve cached users β blocks if initialization is still in progress
const UsersCache& users = GlobalUsersGroupsCache::getUsersCache();
-const GroupsCache& groups = GlobalUsersGroupsCache::getGroupsCache();
-// Use the caches for lookup operations (Windows only)
+// Safely retrieve cached groups β blocks if initialization is still in progress
+const GroupsCache& groups = GlobalUsersGroupsCache::getGroupsCache();
```
-> **Note:** Both accessors are blocking calls. They rely on `std::shared_future` to ensure the background initialization service has completed before returning. This header is Windows-specific and wraps `users_groups_cache.h`.
\ No newline at end of file
+> **Note:** Both accessors use `std::shared_future::get()` semantics internally, making them safe to call from multiple threads simultaneously. Initialization is performed by the background services wired up through `initUsersAndGroupsServices`.
\ No newline at end of file
diff --git a/osquery/core/windows/.handle.md b/osquery/core/windows/.handle.md
index d38911d1f47..d947fa57708 100644
--- a/osquery/core/windows/.handle.md
+++ b/osquery/core/windows/.handle.md
@@ -1,41 +1,54 @@
-RAII-style wrapper class for Windows kernel object handles (`HANDLE`), providing safe open/close lifecycle management for directory and symbolic link objects.
+RAII-style wrapper around a Windows `HANDLE` that provides safe lifecycle management and named object access for directories and symbolic links.
## Key Components
-### `Handle` class
+### `Handle` Class
| Member | Description |
-|---|---|
+|--------|-------------|
| `openDirObj(directory)` | Opens a Windows object directory by name using `OPEN_DIRECTORY` access mask |
| `openSymLinkObj(symlink)` | Opens a Windows symbolic link by name using `SYMBOLIC_LINK_QUERY` access mask |
| `getAsHandle()` | Returns the underlying `HANDLE` value |
-| `close()` | Explicitly releases the handle |
+| `close()` | Explicitly closes the handle |
| `valid()` | Returns `true` if the handle is currently open and valid |
-| `~Handle()` | Destructor automatically closes the handle on scope exit |
+| `~Handle()` | Destructor automatically closes the handle (RAII) |
## Usage Example
-```c
+```cpp
#include "handle.h"
osquery::Handle h;
// Open a Windows object directory
-osquery::Status s = h.openDirObj(L"\\BaseNamedObjects");
-if (!s.ok()) {
+osquery::Status status = h.openDirObj(L"\\BaseNamedObjects");
+if (!status.ok()) {
// handle error
}
+// Use the raw HANDLE if needed
HANDLE raw = h.getAsHandle();
// Check validity before use
if (h.valid()) {
- // perform operations on raw handle
+ // perform operations
}
-// Explicitly close, or destructor will close on scope exit
+// Explicit close (also called automatically on destruction)
h.close();
+
+// Open a symbolic link
+osquery::Handle linkHandle;
+osquery::Status linkStatus = linkHandle.openSymLinkObj(L"\\DosDevices\\C:");
+if (!linkStatus.ok()) {
+ // handle error
+}
+// linkHandle closes automatically when it goes out of scope
```
-> **Note:** This class is Windows-only and relies on `osquery/utils/system/system.h`. The RAII destructor ensures handles are not leaked even if exceptions occur, making it safer than manual `CloseHandle` calls.
\ No newline at end of file
+## Notes
+
+- Defined within the `osquery` namespace
+- Windows-only; depends on `osquery/utils/system/system.h`
+- Returns `osquery::Status` from open methods for consistent error propagation across the osquery framework
\ No newline at end of file
diff --git a/osquery/core/windows/.wmi.md b/osquery/core/windows/.wmi.md
index c5bf928f37f..82b1b82a4ec 100644
--- a/osquery/core/windows/.wmi.md
+++ b/osquery/core/windows/.wmi.md
@@ -1,50 +1,46 @@
-Windows Management Instrumentation (WMI) query abstraction layer for osquery, providing C++ wrapper classes to execute WMI queries and retrieve typed results on Windows systems.
+Windows Management Instrumentation (WMI) wrapper for osquery, providing a C++ interface to query and retrieve Windows system information via WMI queries.
## Key Components
### `WmiMethodArgs`
-Constructs and holds arguments for WMI method calls. Used alongside `WmiResultItem::ExecMethod`.
+Constructs and holds arguments for WMI method calls. Used with `WmiResultItem::ExecMethod`.
- `Put(name, value)` β Adds a typed argument to the call
- `GetArguments()` β Returns the underlying `WmiMethodArgsMap`
### `WmiResultItem`
-Wraps a single `IWbemClassObject` result, providing typed getters for WMI properties:
-- `GetBool`, `GetString`, `GetLong`, `GetUnsignedInt32`, `GetDateTime`, etc.
-- `GetVectorOfStrings`, `GetVectorOfLongs` β For multi-value properties
-- `PrintType(name)` β Debug helper to inspect property VARIANT types
+Wraps a single `IWbemClassObject` result from a WMI query. Provides typed getters:
+- `GetBool`, `GetString`, `GetLong`, `GetUnsignedInt32`, `GetLongLong`, etc.
+- `GetDateTime` β Retrieves local/non-local `FILETIME` values
+- `GetVectorOfStrings` / `GetVectorOfLongs` β Multi-value property support
+- All getters return `Status` indicating success or failure
### `WmiRequest`
-Main entry point for executing WMI queries against a namespace.
-- `CreateWmiRequest(query, nspace)` β Static factory; returns `Expected`
-- `results()` β Returns `std::vector` from the query
-- `getStatus()` β Retrieves execution status
+Primary query class. Manages WMI COM object lifecycle (`IWbemLocator`, `IWbemServices`, `IEnumWbemClassObject`).
+- `CreateWmiRequest(query, nspace)` β Factory method returning `Expected`; defaults to `ROOT\CIMV2`
+- `results()` β Returns the vector of `WmiResultItem` results
- `ExecMethod(object, method, args, out)` β Executes a WMI method on a result object
+- `getStatus()` β Returns the request execution status
### `impl::WmiObjectDeleter`
-Internal RAII deleter for COM `IUnknown` pointers, ensuring `Release()` is called on cleanup.
+Internal RAII deleter for COM `IUnknown` pointers, used with `std::unique_ptr`.
## Usage Example
```cpp
#include
-// Execute a WMI query
+// Query all running processes
auto request = osquery::WmiRequest::CreateWmiRequest(
- "SELECT * FROM Win32_OperatingSystem"
-);
+ "SELECT Name, ProcessId FROM Win32_Process");
if (request) {
- for (const auto& item : request->results()) {
- std::string caption;
- if (item.GetString("Caption", caption).ok()) {
- std::cout << "OS: " << caption << std::endl;
+ for (const auto& item : request->results()) {
+ std::string name;
+ unsigned int pid = 0;
+ item.GetString("Name", name);
+ item.GetUnsignedInt32("ProcessId", pid);
+ std::cout << name << " [" << pid << "]\n";
}
-
- unsigned long long totalMemory = 0;
- if (item.GetUnsignedLongLong("TotalVisibleMemorySize", totalMemory).ok()) {
- std::cout << "RAM (KB): " << totalMemory << std::endl;
- }
- }
}
```
\ No newline at end of file
diff --git a/osquery/database/.database.md b/osquery/database/.database.md
index e9e76edce13..fbd16f2e8b8 100644
--- a/osquery/database/.database.md
+++ b/osquery/database/.database.md
@@ -1,12 +1,12 @@
-Defines the `DatabasePlugin` abstract interface and supporting free functions for osquery's key-value backing storage system, abstracting RocksDB (and SQLite) behind a domain/key API.
+Header defining osquery's persistent backing storage abstraction layer, exposing the `DatabasePlugin` interface and free-function wrappers for key/value database operations across named domains.
## Key Components
-### Domain Constants
+**Domain Constants**
| Constant | Purpose |
|---|---|
-| `kPersistentSettings` | Node UUID, enrollment keys, persisted config |
+| `kPersistentSettings` | Node UUID, enrollment keys, cross-run settings |
| `kQueries` | Scheduled query results |
| `kEvents` | Queued event results |
| `kCarves` | File carve query results |
@@ -14,34 +14,26 @@ Defines the `DatabasePlugin` abstract interface and supporting free functions fo
| `kDistributedQueries` | Distributed query storage |
| `kQueryPerformance` | Query performance statistics |
-### `DatabasePlugin` (abstract class)
-Extends `Plugin`; all backing store implementations must override:
-- `get()` β retrieve a string or int value by domain + key
-- `put()` β store a string or int value
-- `putBatch()` β write multiple key/value pairs atomically
-- `remove()` / `removeRange()` β delete single or ranged keys
-- `scan()` β list keys with optional prefix filter
-- `call()` β registry/extension routing entrypoint
-
-### Free Functions
-- `getDatabaseValue` / `setDatabaseValue` / `setDatabaseBatch` β primary read/write API for all osquery components
-- `deleteDatabaseValue` / `deleteDatabaseRange` β key removal
-- `scanDatabaseKeys` β enumerate keys in a domain
-- `initDatabasePlugin` / `initDatabasePluginForTesting` β lifecycle setup
-- `shutdownDatabase` / `resetDatabase` β teardown and reset
-- `upgradeDatabase` β migrates legacy ptree JSON to RapidJSON format
-- `getOsqueryDatabase` β returns the active `IDatabaseInterface`
+**`DatabasePlugin`** β Abstract base class (extends `Plugin`) implementing the backing store interface. Requires subclasses to implement `get`, `put`, `putBatch`, `remove`, `removeRange`. Provides `call()` for registry/extension routing and `reset()`/`checkDB()` lifecycle helpers.
+
+**Free Functions**
+- `getDatabaseValue` / `setDatabaseValue` / `setDatabaseBatch` β Primary read/write wrappers
+- `deleteDatabaseValue` / `deleteDatabaseRange` β Key removal
+- `scanDatabaseKeys` β Key enumeration with optional prefix filter
+- `initDatabasePlugin` / `shutdownDatabase` / `resetDatabase` β Lifecycle management
+- `upgradeDatabase` β Migrates legacy ptree JSON to RapidJSON format (schema versioned via `kDbCurrentVersion = 2`)
+- `getOsqueryDatabase` β Returns the registry-routed `IDatabaseInterface`
## Usage Example
```c
#include
-// Write a persistent value
+// Store a persistent value
osquery::Status s = osquery::setDatabaseValue(
osquery::kPersistentSettings, "node_key", "abc-123");
-// Read it back
+// Retrieve it later
std::string node_key;
s = osquery::getDatabaseValue(
osquery::kPersistentSettings, "node_key", node_key);
@@ -51,8 +43,6 @@ std::vector keys;
osquery::scanDatabaseKeys(osquery::kQueries, keys);
// Batch write
-osquery::DatabaseStringValueList batch = {
- {"key1", "value1"},
- {"key2", "value2"}};
+osquery::DatabaseStringValueList batch = {{"k1","v1"}, {"k2","v2"}};
osquery::setDatabaseBatch(osquery::kLogs, batch);
```
\ No newline at end of file
diff --git a/osquery/database/tests/.test_utils.md b/osquery/database/tests/.test_utils.md
index f27cb6fbe72..76244676459 100644
--- a/osquery/database/tests/.test_utils.md
+++ b/osquery/database/tests/.test_utils.md
@@ -1,41 +1,43 @@
-Provides a reusable Google Test base class and macro for testing osquery database plugin implementations.
+Provides a reusable base test fixture and macro for writing standardized Google Test suites that validate `osquery` database plugin implementations.
## Key Components
### Macro
-- **`CREATE_DATABASE_TESTS(n)`** β Expands into a full suite of `TEST_F` cases for a given fixture class `n`, covering all standard database operations. Use this in a `.cpp` file to instantiate tests for a specific plugin.
+- **`CREATE_DATABASE_TESTS(n)`** β Expands into a full suite of `TEST_F` declarations for a given fixture class `n`, covering all standard database operations. Eliminates boilerplate when testing multiple plugin backends.
### Class: `DatabasePluginTests`
-A `testing::Test` subclass within the `osquery` namespace that serves as the base fixture for all database plugin test suites.
+Abstract Google Test fixture (`testing::Test`) within the `osquery` namespace. Subclasses must implement `name()` to identify the plugin under test.
| Member | Type | Description |
|---|---|---|
| `path_` | `std::string` | Path to the temporary test database |
-| `previous_path_` | `std::string` | Database path saved before `SetUp` runs |
-| `name()` | pure virtual | Must return the plugin name under test |
-| `SetUp()` / `TearDown()` | lifecycle | Initializes and cleans up the plugin under test |
+| `previous_path_` | `std::string` | Database path saved before `SetUp()` |
+| `SetUp()` / `TearDown()` | overrides | Initializes and cleans up the plugin under test |
+| `name()` | pure virtual | Returns the plugin name for the subclass |
-**Protected test methods** (called by the macro-generated test cases):
+**Protected test methods:**
-`testPluginCheck` Β· `testReset` Β· `testPut` Β· `testPutBatch` Β· `testGet` Β· `testDelete` Β· `testDeleteRange` Β· `testScan` Β· `testScanLimit`
+- `testPluginCheck()` β Validates plugin registration
+- `testReset()` β Tests database reset behavior
+- `testPut()` / `testPutBatch()` β Single and batch write operations
+- `testGet()` β Key lookup
+- `testDelete()` / `testDeleteRange()` β Single and range deletion
+- `testScan()` / `testScanLimit()` β Full and limited key scanning
## Usage Example
```cpp
-#include "test_utils.h"
-
-class RocksDBDatabaseTests : public osquery::DatabasePluginTests {
+// Define a fixture for your plugin backend
+class RocksDBPluginTests : public DatabasePluginTests {
protected:
std::string name() override {
return "rocksdb";
}
};
-// Expands all standard TEST_F cases for RocksDBDatabaseTests
-CREATE_DATABASE_TESTS(RocksDBDatabaseTests);
-```
-
-Adding a new database plugin test suite requires only subclassing `DatabasePluginTests`, implementing `name()`, and invoking `CREATE_DATABASE_TESTS` β no boilerplate test bodies needed.
\ No newline at end of file
+// Expand all standard test cases for this fixture in one line
+CREATE_DATABASE_TESTS(RocksDBPluginTests);
+```
\ No newline at end of file
diff --git a/osquery/dispatcher/.dispatcher.md b/osquery/dispatcher/.dispatcher.md
index 6df777c8bb4..057057754bc 100644
--- a/osquery/dispatcher/.dispatcher.md
+++ b/osquery/dispatcher/.dispatcher.md
@@ -1,74 +1,59 @@
-Manages thread lifecycle and parallel task execution for osquery services, providing a singleton dispatcher that coordinates interruptible background threads.
+Manages concurrent thread execution for osquery services, providing a singleton dispatcher that coordinates parallel asynchronous tasks via interruptible runnable abstractions.
## Key Components
### `InterruptibleRunnable`
-Base class for any runnable that supports clean interruption.
-
-| Member | Description |
-|---|---|
-| `interrupt()` | Signals the runnable to stop (final, non-overridable) |
-| `interrupted()` | Checks if an interrupt has been requested |
-| `pause(milliseconds)` | Interruptible sleep using a condition variable |
-| `stop()` | Pure virtual β subclasses define their shutdown logic |
-| `runnable_name_` | Thread display name |
+Base class for any task that can be paused or stopped mid-execution.
+- `interrupt()` β signals the runnable to stop
+- `interrupted()` β checks current interruption state
+- `pause(milliseconds)` β interruptible sleep using a condition variable
+- `stop()` β pure virtual; subclasses define their shutdown logic
### `InternalRunnable`
-Extends `InterruptibleRunnable` with a thread entrypoint. Non-copyable.
-
-| Member | Description |
-|---|---|
-| `run()` | Thread entrypoint called by `Dispatcher` (final) |
-| `start()` | Pure virtual β subclasses define their work loop |
-| `hasRun()` | Returns whether the thread context has started |
-
-### `Dispatcher` (Singleton)
-Manages all `InternalRunnable` service threads.
-
-| Method | Description |
-|---|---|
-| `instance()` | Returns the singleton instance |
-| `addService(ref)` | Spawns a new service thread (unlimited pool) |
-| `joinServices()` | Blocks until all services complete |
-| `stopServices()` | Interrupts and destroys all running services |
-| `serviceCount()` | Returns the number of active services |
+Extends `InterruptibleRunnable` (non-copyable) as the concrete thread entry point used by the `Dispatcher`.
+- `run()` β thread entrypoint called by the Dispatcher
+- `start()` β pure virtual; subclasses define their work loop
+- `hasRun()` β checks whether the thread has started execution
### Type Aliases
+- `InternalRunnableRef` β `std::shared_ptr`
+- `InternalThreadRef` β `std::unique_ptr`
-```c
-using InternalRunnableRef = std::shared_ptr;
-using InternalThreadRef = std::unique_ptr;
-```
+### `Dispatcher` (Singleton)
+Coordinates lifecycle of all osquery background service threads.
+- `instance()` β returns the singleton instance
+- `addService(service)` β launches a service on a new thread
+- `joinServices()` β blocks until all service threads complete
+- `stopServices()` β signals and tears down all running services
+- `serviceCount()` β returns the number of active services
## Usage Example
-```c
+```cpp
// Define a custom background service
-class MyService : public InternalRunnable {
+class MyService : public osquery::InternalRunnable {
public:
MyService() : InternalRunnable("MyService") {}
protected:
void start() override {
while (!interrupted()) {
- // do work
- pause(std::chrono::milliseconds(500));
+ // Do periodic work
+ pause(std::chrono::milliseconds(1000));
}
}
void stop() override {
- // cleanup
+ // Cleanup on shutdown
}
};
// Register and launch the service
-auto svc = std::make_shared();
-osquery::Dispatcher::addService(svc);
+auto service = std::make_shared();
+osquery::Dispatcher::addService(service);
-// Later, cleanly shut everything down
+// Gracefully stop all services on shutdown
osquery::Dispatcher::stopServices();
osquery::Dispatcher::joinServices();
-```
-
-> **Note:** `Dispatcher` is a singleton β never construct it directly. Use `Dispatcher::instance()`. Services are not subject to a fixed thread pool size, unlike the underlying Thrift pool.
\ No newline at end of file
+```
\ No newline at end of file
diff --git a/osquery/dispatcher/.distributed_runner.md b/osquery/dispatcher/.distributed_runner.md
index c52d1a98aff..050c9b0285a 100644
--- a/osquery/dispatcher/.distributed_runner.md
+++ b/osquery/dispatcher/.distributed_runner.md
@@ -1,32 +1,34 @@
-Declares the `DistributedRunner` service thread responsible for executing distributed queries within the osquery dispatcher framework.
+Defines the `DistributedRunner` service thread responsible for executing distributed queries within the osquery dispatcher framework.
## Key Components
-- **`DistributedRunner`** β A `InternalRunnable` subclass that runs as a long-lived Dispatcher service thread, implementing the distributed query polling/execution loop.
- - `start()` β Entry point invoked by the Dispatcher when the thread is scheduled.
-- **`startDistributed()`** β Factory/helper function to initialize and register the `DistributedRunner` with the osquery Dispatcher.
+- **`DistributedRunner`** β A `InternalRunnable` subclass that runs as a persistent Dispatcher service thread, handling distributed query execution.
+ - `start()` β Thread entry point override; contains the main distributed query processing loop.
-## Usage Example
+- **`startDistributed()`** β Free function that initializes and registers the `DistributedRunner` with the osquery Dispatcher.
-```cpp
-#include
+## Usage Example
-// Start the distributed query service (typically called during osquery startup)
-Status s = osquery::startDistributed();
+```c
+// Start the distributed query runner service
+Status s = startDistributed();
if (!s.ok()) {
- LOG(ERROR) << "Failed to start distributed runner: " << s.getMessage();
+ LOG(ERROR) << "Failed to start distributed runner: " << s.getMessage();
}
-```
-Internally, the runner is registered via the Dispatcher:
-
-```cpp
-// Inside startDistributed() β conceptual implementation
-Status startDistributed() {
- Dispatcher::addService(std::make_shared());
- return Status::success();
-}
+// The runner is managed by the Dispatcher; to integrate a custom runner:
+class MyDistributedRunner : public DistributedRunner {
+ public:
+ void start() override {
+ // Custom distributed query handling logic
+ DistributedRunner::start();
+ }
+};
```
-> **Note:** `DistributedRunner` is intended to be managed exclusively by the osquery `Dispatcher`. Do not instantiate or call `start()` directly β use `startDistributed()` instead to ensure proper lifecycle management.
\ No newline at end of file
+## Notes
+
+- Inherits lifecycle management (start/stop/join) from `InternalRunnable` via the Dispatcher subsystem.
+- Registered under the name `"DistributedRunner"` for identification within the Dispatcher thread registry.
+- Intended to be launched once via `startDistributed()` rather than instantiated directly.
\ No newline at end of file
diff --git a/osquery/dispatcher/.scheduler.md b/osquery/dispatcher/.scheduler.md
index 01692c14232..58a16c32e84 100644
--- a/osquery/dispatcher/.scheduler.md
+++ b/osquery/dispatcher/.scheduler.md
@@ -1,54 +1,45 @@
-Defines the `SchedulerRunner` class and supporting utilities for executing scheduled osquery SQL queries at configurable intervals within the osquery dispatcher framework.
+Defines the `SchedulerRunner` class and related utilities for executing scheduled osquery SQL queries at configurable intervals within the dispatcher framework.
## Key Components
### `SchedulerRunner` (class)
-A `InternalRunnable` dispatcher service thread that drives osquery's schedule execution loop.
+A `InternalRunnable`-derived dispatcher service thread that drives the osquery schedule loop.
| Member | Description |
-|---|---|
-| `SchedulerRunner(timeout, interval, max_time_drift)` | Constructor; configures loop timeout, step interval, and optional drift cap |
-| `start()` | Thread entry point; runs the scheduling loop |
-| `stop()` | Interrupt/stop hook (no-op implementation) |
-| `getCurrentTimeDrift()` | Returns accumulated time drift in milliseconds |
-
-### Private Helpers
-| Method | Description |
-|---|---|
-| `calculateTimeDriftAndMaybePause()` | Tracks loop step duration and compensates for drift |
-| `maybeRunDecorators()` | Fires interval-based query decorators |
-| `maybeReloadSchedule()` | Checks and applies config schedule changes |
-| `maybeFlushLogs()` | Conditionally flushes buffered status logs |
-| `maybeScheduleCarves()` | Triggers file carve requests on schedule |
+|--------|-------------|
+| `SchedulerRunner(timeout, interval, max_time_drift)` | Constructs runner with step interval, max steps, and optional drift cap |
+| `start()` | Thread entry point; runs the schedule loop |
+| `stop()` | Interrupt/stop hook (no-op) |
+| `getCurrentTimeDrift()` | Returns accumulated millisecond drift |
+| `calculateTimeDriftAndMaybePause()` | Adjusts sleep to compensate for loop overrun |
+| `maybeRunDecorators()` | Fires interval-based decorator queries |
+| `maybeReloadSchedule()` | Checks for config schedule changes |
+| `maybeFlushLogs()` | Flushes buffered status logs when due |
+| `maybeScheduleCarves()` | Enqueues pending file carve requests |
### Free Functions
+
| Function | Description |
-|---|---|
-| `monitor(name, query)` | Executes a named `ScheduledQuery` and returns an `SQLInternal` result |
+|----------|-------------|
+| `monitor(name, query)` | Executes a named `ScheduledQuery` and returns a `SQLInternal` result |
| `startScheduler()` | Starts the scheduler using config-defined settings |
-| `startScheduler(timeout, interval)` | Starts the scheduler with explicit timeout and interval (used in tests) |
+| `startScheduler(timeout, interval)` | Overload for testing with explicit timeout/interval |
## Usage Example
```cpp
-#include "osquery/scheduler/scheduler.h"
-
-// Start the scheduler using the loaded osquery config schedule
+// Production start β reads schedule from config
osquery::startScheduler();
-// Or start with explicit parameters (e.g., in tests)
-osquery::startScheduler(
- /*timeout=*/3600UL, // run for 3600 steps
- /*interval=*/60 // execute every 60 seconds
-);
-
-// Manually monitor a specific scheduled query
-osquery::ScheduledQuery sq;
-sq.query = "SELECT * FROM processes;";
-sq.interval = 60;
-
-osquery::SQLInternal result = osquery::monitor("process_monitor", sq);
-```
+// Test/controlled start β 60 steps, 1-second interval
+osquery::startScheduler(60UL, 1);
-> **Note:** `request_shutdown_on_expiration` defaults to `true` in production but is suppressed during unit tests via `FRIEND_TEST(TLSConfigTests, test_runner_and_scheduler)` to prevent premature process exit.
\ No newline at end of file
+// Construct runner directly with drift cap of 500ms
+auto runner = std::make_shared(
+ 3600UL, // timeout (steps)
+ 60, // interval (seconds)
+ std::chrono::milliseconds(500) // max allowed drift
+);
+Dispatcher::addService(runner);
+```
\ No newline at end of file
diff --git a/osquery/distributed/.distributed.md b/osquery/distributed/.distributed.md
index e9b7444e2a4..ae034c9449d 100644
--- a/osquery/distributed/.distributed.md
+++ b/osquery/distributed/.distributed.md
@@ -1,27 +1,24 @@
-Defines the interfaces and data structures for osquery's distributed query system, enabling remote query execution, result serialization, and denylist management across endpoints.
+Defines the core types, serialization utilities, and classes for osquery's distributed query system, enabling remote query dispatch and result collection.
## Key Components
### Structs
-- **`DistributedQueryRequest`** β Holds a query string and its unique ID for a pending distributed query
-- **`DistributedQueryResult`** β Holds the request, result rows, column names, status, and message from a completed query execution
+- **`DistributedQueryRequest`** β Holds a query string and its associated ID for remote execution
+- **`DistributedQueryResult`** β Contains the request, result rows, column names, status, and message from a completed query
### Free Functions
-
-| Function | Description |
-|---|---|
-| `serializeDistributedQueryRequest[JSON]` | Serialize a request to JSON tree or string |
-| `deserializeDistributedQueryRequest[JSON]` | Deserialize a request from JSON tree or string |
-| `serializeDistributedQueryResult[JSON]` | Serialize a result to JSON tree or string |
-| `deserializeDistributedQueryResult[JSON]` | Deserialize a result from JSON tree or string |
-| `hashQuery` | Returns SHA-256 hex digest of a query string |
-| `denylistDuration` | Returns configured denylist duration in seconds |
-| `denylistedQueryTimestampExpired` | Checks if a denylisted query's timeout has elapsed |
+- **`serializeDistributedQueryRequest`** / **`serializeDistributedQueryRequestJSON`** β Serialize a request to a rapidjson object or JSON string
+- **`deserializeDistributedQueryRequest`** / **`deserializeDistributedQueryRequestJSON`** β Deserialize a request from a rapidjson object or JSON string
+- **`serializeDistributedQueryResult`** / **`serializeDistributedQueryResultJSON`** β Serialize a result to a rapidjson object or JSON string
+- **`deserializeDistributedQueryResult`** / **`deserializeDistributedQueryResultJSON`** β Deserialize a result from a rapidjson object or JSON string
+- **`hashQuery`** β Returns the SHA-256 hex digest of a query string (used as a denylist key)
+- **`denylistDuration`** β Returns the configured denylist duration in seconds
+- **`denylistedQueryTimestampExpired`** β Checks whether a denylist timestamp has expired
### Classes
-- **`DistributedPlugin`** β Abstract plugin base; implementors must provide `getQueries()` and `writeResults()` to integrate with a remote query backend
-- **`Distributed`** β Orchestrates the full distributed query lifecycle: pulling, executing, tracking running state, recording performance, and flushing results
+- **`DistributedPlugin`** β Abstract plugin base; implementors provide `getQueries()` and `writeResults()` to integrate a remote query backend
+- **`Distributed`** β Orchestrates the full distributed query lifecycle: pulling work, executing queries, tracking running state, recording performance, and flushing results
## Usage Example
@@ -30,22 +27,19 @@ Defines the interfaces and data structures for osquery's distributed query syste
auto dist = osquery::Distributed();
while (true) {
- // Pull pending queries from remote server
- dist.pullUpdates();
-
- if (dist.getPendingQueryCount() > 0) {
- // Execute all pending queries and queue results
- dist.runQueries();
- }
+ dist.pullUpdates();
- // Serialize and inspect buffered results
- std::string json;
- dist.serializeResults(json);
+ if (dist.getPendingQueryCount() > 0) {
+ dist.runQueries();
+ }
}
-```
-## Notes
+// Serialize results before flushing
+std::string json;
+dist.serializeResults(json);
-- Query deduplication is enforced via SHA-256 hashing (`hashQuery`) combined with denylist tracking (`checkAndSetAsRunning`) to prevent re-execution within the configured denylist window
-- Discovery queries gate execution: if a discovery query returns no rows, its associated distributed query is skipped
-- Performance statistics per query are recorded in `performance_` and reported alongside results
\ No newline at end of file
+// Serialize a single result to JSON
+osquery::DistributedQueryResult result;
+std::string resultJson;
+osquery::serializeDistributedQueryResultJSON(result, resultJson);
+```
\ No newline at end of file
diff --git a/osquery/events/.eventer.md b/osquery/events/.eventer.md
index 739769904da..8647b7d3acc 100644
--- a/osquery/events/.eventer.md
+++ b/osquery/events/.eventer.md
@@ -1,40 +1,41 @@
-Defines the base `Eventer` class and `EventState` enum used to track the lifecycle state of event publishers and subscribers within osquery's eventing system.
+Defines the base `Eventer` class and `EventState` enum used to track the lifecycle state of osquery EventSubscribers and Publishers during initialization and runtime.
## Key Components
### `EventState` (enum class)
-Represents the possible lifecycle states of an event publisher or subscriber:
+Represents the possible lifecycle states of a subscriber or publisher:
-| Value | Description |
+| Value | Meaning |
|---|---|
-| `EVENT_NONE` | Default uninitialized state |
-| `EVENT_SETUP` | Subscriber attached and setup complete |
-| `EVENT_RUNNING` | Ready to receive events |
+| `EVENT_NONE` | Default, uninitialized state |
+| `EVENT_SETUP` | Attached and setup has run |
+| `EVENT_RUNNING` | Ready to accept events |
| `EVENT_PAUSED` | Initialized but not accepting events |
-| `EVENT_FAILED` | Initialization failed or offline |
+| `EVENT_FAILED` | Failed to initialize or offline |
### `Eventer` (class)
-Base class providing state management for event publishers and subscribers.
+Base class providing state management for event subscribers and publishers.
| Member | Access | Description |
|---|---|---|
-| `state() const` | `public` | Returns current `EventState` |
+| `state()` | `public` | Returns current `EventState` |
| `state(EventState)` | `protected` | Sets the current state |
| `state_` | `private` | Internal state storage, defaults to `EVENT_NONE` |
-
-`EventFactory` is declared a `friend` class, granting it direct access to internal state.
+| `EventFactory` | `friend` | Granted direct access for lifecycle management |
## Usage Example
```cpp
-#include
+#include
+// Typically subclassed by an EventSubscriber or EventPublisher
class MySubscriber : public Eventer {
public:
void initialize() {
// Transition to running after setup
state(EventState::EVENT_SETUP);
+
if (setupSucceeded()) {
state(EventState::EVENT_RUNNING);
} else {
@@ -44,8 +45,10 @@ class MySubscriber : public Eventer {
void checkStatus() {
if (state() == EventState::EVENT_RUNNING) {
- // Accept and process events
+ // Accept and process incoming events
}
}
};
-```
\ No newline at end of file
+```
+
+> `EventFactory` is the only external class with direct access to `Eventer`'s private members, maintaining controlled state transitions across the event subsystem.
\ No newline at end of file
diff --git a/osquery/events/.eventfactory.md b/osquery/events/.eventfactory.md
index c83bdcca4f3..44709b00fe9 100644
--- a/osquery/events/.eventfactory.md
+++ b/osquery/events/.eventfactory.md
@@ -1,47 +1,67 @@
-Singleton factory class for managing osquery event publishers, subscribers, and subscriptions throughout the application lifecycle.
+Singleton factory that manages the full lifecycle of event publishers and subscribers in osquery's eventing system β handling registration, subscription wiring, run loop dispatch, and teardown.
## Key Components
-| Member | Type | Description |
-|--------|------|-------------|
-| `getInstance()` | Static method | Returns the singleton `EventFactory` instance |
-| `registerEventPublisher()` | Static method | Registers an `EventPublisher` plugin with the factory |
-| `registerEventSubscriber()` | Template method | Registers an `EventSubscriber` by type or instance |
-| `addSubscription()` | Static method | Binds a `SubscriptionContext` and `EventCallback` to a publisher |
-| `deregisterEventPublisher()` | Static method | Halts a publisher's run loop and removes it from the factory |
-| `getEventPublisher()` | Static method | Retrieves a registered publisher by name |
-| `getEventSubscriber()` | Static method | Retrieves a registered subscriber by name |
-| `fire()` | Template method | Fires an `EventContext` into a publisher's subscriber callbacks |
-| `getType()` | Template method | Resolves the registry plugin name for a publisher type |
-| `delay()` | Static method | Spawns all registered publisher run loop threads |
-| `end()` | Static method | Terminates all publisher run loops and optionally joins threads |
-| `configUpdate()` | Static method | Notifies publishers/subscribers of configuration changes |
+### `EventFactory` (Singleton Class)
+The central coordinator for all osquery event infrastructure. Accessed via `EventFactory::getInstance()`.
+
+**Publisher Management**
+- `registerEventPublisher(pub)` β registers an `EventPublisher` plugin instance
+- `deregisterEventPublisher(pub/type_id)` β halts the run loop and cleans up
+- `getEventPublisher(pub)` β retrieves a registered publisher by name
+- `numEventPublishers()` β returns count of registered publishers
+- `publisherTypes()` β returns all registered publisher registry names
+
+**Subscriber Management**
+- `registerEventSubscriber()` β template registration; creates and registers a typed subscriber
+- `registerEventSubscriber(sub)` β registration by plugin instance
+- `deregisterEventSubscriber(sub)` β removes a subscriber by name
+- `getEventSubscriber(sub)` β retrieves a registered subscriber
+- `subscriberNames()` β returns all subscriber registry names
+- `exists(sub)` β checks if a subscriber is registered
+
+**Subscription Wiring**
+- `addSubscription(type_id, name_id, sc, cb)` β creates and attaches a `Subscription` to a publisher
+- `addSubscription(type_id, subscription)` β attaches a pre-built `Subscription` instance
+- `numSubscriptions(type_id)` β counts subscriptions for a given publisher
+
+**Run Loop Control**
+- `delay()` β spawns all publisher run loop threads
+- `run(type_id)` β entry point for a single publisher's dispatch thread
+- `end(join)` β shuts down all publishers; optionally joins threads
+- `fire(ec)` β fires an `EventContext` into a publisher from a static callback
+
+**Utilities**
+- `getType()` β returns the registry name for a publisher type
+- `configUpdate()` β notifies the factory of configuration changes
+- `addForwarder(logger)` / `forwardEvent(event)` β routes events to logger plugins
## Usage Example
```cpp
-// Register a publisher plugin
+// Register a publisher and subscriber
EventFactory::registerEventPublisher(pub_plugin_ref);
-
-// Register a subscriber by type
EventFactory::registerEventSubscriber();
-// Add a subscription with context and callback
+// Wire a subscription with a callback
auto sc = std::make_shared();
-EventFactory::addSubscription("my_publisher", "my_subscriber", sc,
- [](const EventContextRef& ec, const SubscriptionContextRef& sc) {
- // Handle event
- return Status::success();
- });
-
-// Fire an event from a static publisher callback
-EventContextRef ec = std::make_shared();
-EventFactory::fire(ec);
+EventFactory::addSubscription(
+ "my_publisher",
+ "my_subscriber",
+ sc,
+ [](const EventContextRef& ec, const SubscriptionContextRef& sc) {
+ // handle event
+ return Status::success();
+ }
+);
// Start all publisher run loops
EventFactory::delay();
-// Shutdown all publishers (with thread join)
-EventFactory::end(true);
+// Fire an event from a static publisher callback
+EventFactory::fire(event_context);
+
+// Shutdown
+EventFactory::end(true /* join threads */);
```
\ No newline at end of file
diff --git a/osquery/events/.eventpublisherplugin.md b/osquery/events/.eventpublisherplugin.md
index 9903fac46e1..3777ff0336b 100644
--- a/osquery/events/.eventpublisherplugin.md
+++ b/osquery/events/.eventpublisherplugin.md
@@ -1,37 +1,31 @@
-Defines the `EventPublisherPlugin` base class for osquery's event-driven architecture, providing the lifecycle interface that all event publishers must implement to register OS-level callbacks, manage subscriptions, and fire events to subscribers.
+Plugin interface for osquery event publishers, defining the lifecycle and subscription management API for event-driven data collection.
## Key Components
-### Class: `EventPublisherPlugin`
-Inherits from `Plugin`, `InterruptibleRunnable`, and `Eventer`. Serves as the abstract base for all event publisher implementations.
+### `EventPublisherPlugin` Class
+Inherits from `Plugin`, `InterruptibleRunnable`, and `Eventer`. Provides the base class for all osquery event publishers.
**Lifecycle Methods**
-| Method | Description |
-|--------|-------------|
-| `setUp()` | Initialize handles and register OS API callbacks (called before run loop) |
-| `configure()` | Re-optimize subscriptions (e.g., dedup inotify paths) when subscriptions change |
-| `tearDown()` | Release handles and clean up resources before exit |
-| `run()` | Single iteration of the publisher's run loop; return `FAILED` to exit |
-| `stop()` | Signal the run loop to terminate (called by `EventFactory`) |
+- `setUp()` β Called before the run loop starts; opens handles and registers OS API callbacks
+- `configure()` β Called when subscriptions change; allows optimization (e.g., deduplicating `inotify` paths)
+- `run()` β Single step of the publisher's run loop; returning `FAILED` exits the loop
+- `tearDown()` β Cleans up handles and resources on shutdown; may be called multiple times
+- `stop()` β Signals the run loop to terminate via `isEnding`
**Subscription Management**
-| Method | Description |
-|--------|-------------|
-| `addSubscription(sub)` | Register a new `SubscriptionRef` with this publisher |
-| `removeSubscriptions(subscriber)` | Remove all subscriptions for a named subscriber |
-| `numSubscriptions()` | Returns active subscription count |
+- `addSubscription(subscription)` β Registers a new `SubscriptionRef` with this publisher
+- `removeSubscriptions(subscriber)` β Removes all subscriptions for a named subscriber
+- `numSubscriptions()` β Returns the active subscription count
**State Inspection**
-- `isEnding()` / `hasStarted()` β get/set publisher lifecycle state
-- `numEvents()` β total fired event count
-- `restartCount()` β run loop restart iterations
+- `isEnding()` / `hasStarted()` / `restartCount()` β Query run loop lifecycle state
+- `numEvents()` β Returns total `EventContextID` count fired
-### Protected Members
-- `fire(ec, time)` β dispatches an `EventContext` to all matching subscribers
-- `fireCallback(sub, ec)` β pure virtual; typed publishers implement actual dispatch
-- `subscriptions_` β the internal `SubscriptionVector`
-- `next_ec_id_` β atomic event context ID counter
+**Protected Internals**
+- `fire(ec, time)` β Enumerates subscriptions and dispatches event callbacks
+- `fireCallback(sub, ec)` β Pure virtual; implemented by typed publishers to invoke subscriber callbacks
+- `subscriptions_` / `subscription_lock_` β Thread-safe subscription storage
## Usage Example
@@ -39,24 +33,23 @@ Inherits from `Plugin`, `InterruptibleRunnable`, and `Eventer`. Serves as the ab
class MyPublisher : public EventPublisherPlugin {
public:
Status setUp() override {
- // Open OS handle or register callback
+ // Register OS-level event source
return Status::success();
}
Status run() override {
auto ec = createEventContext();
- fire(ec); // dispatches to all subscribers
+ // Populate ec with event data
+ fire(ec);
return Status::success();
}
- void tearDown() override {
- // Close handles
- }
-
protected:
void fireCallback(const SubscriptionRef& sub,
const EventContextRef& ec) const override {
- // Invoke subscriber's typed callback
+ // Invoke subscriber-specific callback
}
};
-```
\ No newline at end of file
+```
+
+> **Note:** `interrupted()` is deprecated β use `isEnding()` to check publisher termination state. Copy construction and assignment are explicitly deleted.
\ No newline at end of file
diff --git a/osquery/events/.events.md b/osquery/events/.events.md
index 185e2df9624..9b2e23aaf1f 100644
--- a/osquery/events/.events.md
+++ b/osquery/events/.events.md
@@ -1,26 +1,29 @@
-Utility header declaring event system lifecycle functions within the `osquery` namespace for managing event publisher run loops and query denylist enforcement.
+Provides event system utilities for managing publisher lifecycles and query access control within the osquery event framework.
## Key Components
-| Function | Description |
-|---|---|
-| `attachEvents()` | Iterates the event publisher registry and creates run loops for each publisher via the event factory |
-| `enforceEventsDenylist(query)` | Returns `true` if the given query operates exclusively on event-based tables and should be denylisted |
+- **`attachEvents()`** β Iterates the event publisher registry and creates run loops for each publisher using the event factory
+- **`enforceEventsDenylist(const std::string& query)`** β Evaluates whether a query exclusively targets event-based tables and should be denied/blocked
## Usage Example
```c
#include "events.h"
-// Initialize all registered event publishers
+// Initialize all registered event publishers at startup
osquery::attachEvents();
-// Check if a query should be denied based on event-table usage
-std::string query = "SELECT * FROM process_events";
-if (osquery::enforceEventsDenylist(query)) {
- // Query is denylist-eligible; skip or block execution
+// Before executing a query, check if it should be denied
+std::string incomingQuery = "SELECT * FROM process_events";
+if (osquery::enforceEventsDenylist(incomingQuery)) {
+ // Query operates only on event-based tables β block execution
+ return;
}
```
-> **Note:** `attachEvents()` is typically called once during daemon startup to wire up all registered publishers. `enforceEventsDenylist` is used during query scheduling to prevent high-frequency polling on purely event-driven tables.
\ No newline at end of file
+## Notes
+
+- Both functions live in the `osquery` namespace
+- `attachEvents()` is typically called during daemon initialization to start all event-driven subscribers
+- `enforceEventsDenylist()` acts as a guard for queries that would only consume event-table data, preventing potential abuse or excessive resource usage
\ No newline at end of file
diff --git a/osquery/events/.eventsubscriberplugin.md b/osquery/events/.eventsubscriberplugin.md
index 9338289cef4..b904f6a747a 100644
--- a/osquery/events/.eventsubscriberplugin.md
+++ b/osquery/events/.eventsubscriberplugin.md
@@ -1,29 +1,29 @@
-Defines the `EventSubscriberPlugin` class, the base interface for osquery event subscribers that receive, store, and expose event data as queryable table rows via a backing database store.
+Defines the `EventSubscriberPlugin` class, the base interface for osquery event subscribers that receive, store, and expose event data as queryable table rows via a backing store.
## Key Components
### Class: `EventSubscriberPlugin`
-Inherits from `Plugin` and `Eventer`. Manages event ingestion, indexed storage, expiration, and query-time row generation.
+Inherits from `Plugin` and `Eventer`. Manages the full lifecycle of event subscription, storage, indexing, expiration, and table generation.
-### Core Methods
+### Key Methods
| Method | Description |
-|---|---|
-| `init()` | Override to register `Subscription`s with an `EventPublisher` |
-| `call(PluginRequest, PluginResponse)` | Plugin dispatch entrypoint |
-| `addBatch(row_list)` | Store a batch of parsed event rows to the backing store (preferred API) |
-| `add(row)` | *(Deprecated)* Store a single event row β use `addBatch()` instead |
-| `genTable(yield, ctx)` | Table generation entrypoint; retrieves stored events filtered by query time window |
-| `generateRows(...)` | Static: enumerate stored events within a `[start_time, end_time]` range |
-| `expireEventBatches(...)` | Static: prune old event batches from backing store |
-| `removeOverflowingEventBatches(...)` | Static: enforce maximum batch count |
-| `getOptimizeData(...)` / `setOptimizeData(...)` | Static: manage query optimization checkpoints |
-
-### Supporting Structures
-
-- **`Context`** β Holds the database namespace, event index, last query/event timestamps
-- **`GenerateRowsResult`** β Returns pagination state (`isEnd`, `last_time`, `last_id`) from `generateRows`
+|--------|-------------|
+| `init()` | Entry point for registering subscriptions with the EventPublisher |
+| `addBatch(row_list)` | Stores a batch of parsed event rows in the backing store (preferred API) |
+| `add(r)` | *(Deprecated)* Stores a single event row; use `addBatch()` instead |
+| `genTable(yield, ctx)` | Main entrypoint for table generation at query time |
+| `generateRows(...)` | Retrieves stored events filtered by time window |
+| `getEventsExpiry()` | Returns the expiration timeout for this event type |
+| `getEventBatchesMax()` | Returns the maximum number of stored event batches |
+| `getOptimizeData(...)` | Reads optimization state (last event time/ID) from the database |
+| `setOptimizeData(...)` | Writes optimization state to the database |
+
+### Supporting Types
+
+- **`Context`** β Holds per-subscriber state: database namespace, event index, last query time, and last event ID
+- **`GenerateRowsResult`** β Return type for `generateRows`, including end-of-range flag and last visited time/ID
## Usage Example
@@ -31,19 +31,22 @@ Inherits from `Plugin` and `Eventer`. Manages event ingestion, indexed storage,
class MySubscriber : public EventSubscriber {
public:
Status init() override {
- auto sub = createSubscription();
- return EventFactory::addSubscription(getType(), sub);
+ // Create and add a subscription
+ auto sc = MyPublisher::createSubscriptionContext();
+ sc->path = "/etc/passwd";
+ subscribe(&MySubscriber::callback, sc);
+ return Status::success();
}
- Status Callback(const EventContextRef& ec, const SubscriptionContextRef& sc) {
+ Status callback(const ECRef& ec, const SCRef& sc) {
Row r;
+ r["path"] = ec->path;
r["action"] = ec->action;
- r["time"] = INTEGER(ec->time);
-
- std::vector batch = {r};
- return addBatch(batch); // preferred over deprecated add()
+ // Batch rows and store them
+ std::vector rows = {r};
+ return addBatch(rows);
}
};
```
-> **Note:** `add()` is deprecated. Always use `addBatch()` to group events together for efficient indexed storage and reduced write overhead.
\ No newline at end of file
+> **Note:** Always use `addBatch()` over the deprecated `add()`. Subscriptions must be registered in `init()`, not the constructor, to ensure the EventPublisher is fully initialized.
\ No newline at end of file
diff --git a/osquery/events/.subscription.md b/osquery/events/.subscription.md
index b7de73f51af..861d2126fc6 100644
--- a/osquery/events/.subscription.md
+++ b/osquery/events/.subscription.md
@@ -1,40 +1,38 @@
-Defines the `Subscription` struct used to configure an `EventPublisher` and bind event callbacks to a `SubscriptionContext` within osquery's event framework.
+Defines the `Subscription` struct and related type aliases used to configure event publishers and bind callbacks within osquery's event framework.
## Key Components
-| Symbol | Type | Description |
-|---|---|---|
-| `EventCallback` | `using` alias | Function signature `Status(const EventContextRef&, const SubscriptionContextRef&)` invoked when a matching event fires |
-| `SubscriptionRef` | `using` alias | `shared_ptr` for shared ownership of a subscription |
-| `SubscriptionVector` | `using` alias | `vector` used by publishers to track all active subscriptions |
-| `Subscription` | `struct` | Non-copyable aggregate holding a subscriber name, context, and callback |
-| `Subscription::create()` | static factory | Two overloads β name-only, or name + context + optional callback |
+- **`EventCallback`** β Type alias for `std::function`; the callback signature fired when a matching event occurs.
+- **`SubscriptionRef`** β `std::shared_ptr` for safe shared ownership.
+- **`SubscriptionVector`** β `std::vector` used by publishers to track all active subscriptions.
+- **`Subscription`** (struct) β Core non-copyable struct holding:
+ - `subscriber_name` β Name of the owning `EventSubscriber`.
+ - `context` β Publisher-specific `SubscriptionContextRef` defining event scope/filters.
+ - `callback` β The `EventCallback` to invoke on matching events.
+ - `create()` (static, x2) β Factory methods to construct a `SubscriptionRef`, with or without a context and callback.
## Usage Example
```cpp
#include
-// Define a callback matching the EventCallback signature
-Status onFileEvent(const EventContextRef& ec,
- const SubscriptionContextRef& sc) {
- // Handle the event
+// Define a callback
+EventCallback my_callback = [](const EventContextRef& ec,
+ const SubscriptionContextRef& sc) -> Status {
+ // Handle event
return Status::success();
-}
+};
-// Create a subscription with context and callback
+// Create a subscription context (publisher-specific)
auto ctx = std::make_shared();
ctx->path = "/etc/passwd";
-SubscriptionRef sub = Subscription::create(
- "my_subscriber", // EventSubscriber name
- ctx, // Publisher-specific context
- onFileEvent // Callback fired on matching events
-);
+// Create the subscription
+auto sub = Subscription::create("my_subscriber", ctx, my_callback);
-// Register via EventFactory
+// Register with the event publisher via EventFactory
EventFactory::addSubscription("MyEventPublisher", sub);
```
-> **Note:** `Subscription` inherits `boost::noncopyable` β always pass instances via `SubscriptionRef` (`shared_ptr`). The default constructor is explicitly deleted; use the static `create()` factory methods.
\ No newline at end of file
+> **Note:** `Subscription` is non-copyable (`boost::noncopyable`). Always use `SubscriptionRef` (shared pointer) when passing or storing subscriptions. The default constructor is deleted β use the `create()` factory methods.
\ No newline at end of file
diff --git a/osquery/events/darwin/.diskarbitration.md b/osquery/events/darwin/.diskarbitration.md
index fe2b809a169..8336295e461 100644
--- a/osquery/events/darwin/.diskarbitration.md
+++ b/osquery/events/darwin/.diskarbitration.md
@@ -1,50 +1,51 @@
-Provides the osquery event publisher interface for monitoring macOS disk mount/unmount events via the DiskArbitration framework.
+Provides the macOS Disk Arbitration event publisher interface for osquery, enabling subscription to disk mount/unmount events on macOS systems.
## Key Components
### Macros
-
-| Macro | Purpose |
-|---|---|
-| `kIOPropertyProtocolCharacteristicsKey_` | IOKit key for protocol characteristics lookup |
-| `kVirtualInterfaceLocation_` | Key identifying virtual disk interface paths |
-| `kDAAppearanceTime_` | Key for disk appearance timestamp |
+- `kIOPropertyProtocolCharacteristicsKey_` β IOKit key for protocol characteristics lookup
+- `kVirtualInterfaceLocation_` β Key identifying virtual disk interface location paths
+- `kDAAppearanceTime_` β Key for disk appearance timestamp
### Structs
-
- **`DiskArbitrationSubscriptionContext`** β Subscription filter; `physical_disks` flag limits events to physical vs. virtual (DMG) disks
-- **`DiskArbitrationEventContext`** β Event payload carrying disk metadata: `action`, `path`, `device_path`, `uuid`, `size`, `filesystem`, `vendor`, `checksum`, and mount capability flags
+- **`DiskArbitrationEventContext`** β Event payload containing disk metadata: `action`, `path`, `device_path`, `name`, `uuid`, `size`, `ejectable`, `mountable`, `writable`, `filesystem`, `vendor`, `checksum`, and more
### Type Aliases
-
- `DiskArbitrationEventContextRef` β `shared_ptr`
- `DiskArbitrationSubscriptionContextRef` β `shared_ptr`
### Class: `DiskArbitrationEventPublisher`
+Extends `EventPublisher`.
-Extends `EventPublisher` to wrap macOS `DASession` callbacks into osquery events.
-
-| Member | Description |
-|---|---|
-| `run()` | Starts the `CFRunLoop` and registers DA session callbacks |
-| `tearDown()` | Releases DA session and run loop resources |
+| Method | Description |
+|--------|-------------|
+| `run()` | Starts the DA session and CFRunLoop |
+| `tearDown()` | Cleans up session resources |
| `shouldFire()` | Filters events against subscription context |
-| `DiskAppearedCallback()` | Static DA callback for disk mount events |
-| `DiskDisappearedCallback()` | Static DA callback for disk unmount events |
-| `extractUdifChecksum()` | Reads checksum from UDIF (DMG) disk images |
-| `fire()` | Builds and dispatches `DiskArbitrationEventContext` from a `CFDictionaryRef` |
+| `DiskAppearedCallback()` | Static DA callback on disk mount |
+| `DiskDisappearedCallback()` | Static DA callback on disk unmount |
+| `extractUdifChecksum()` | Extracts checksum from DMG (UDIF) files |
+| `getProperty()` | Reads a `CFStringRef` value from a `CFDictionaryRef` |
+
+**Private members:** `DASessionRef session_`, `CFRunLoopRef run_loop_`, `Mutex mutex_`
## Usage Example
```cpp
-// Subscribe to physical disk events only
+// Subscribe to disk arbitration events (all disks)
auto sc = std::make_shared();
-sc->physical_disks = true;
+sc->physical_disks = true; // restrict to physical disks only
-auto sub = EventFactory::addSubscription(
+EventFactory::addSubscription(
"diskarbitration",
- EventSubscriberPlugin::SubscriptionAction::ADD,
- sc,
- callback);
-```
\ No newline at end of file
+ Subscription::create("my_subscriber", sc,
+ [](const DiskArbitrationEventContextRef& ec,
+ const DiskArbitrationSubscriptionContextRef&) {
+ LOG(INFO) << ec->action << " " << ec->path
+ << " (" << ec->filesystem << ")";
+ }));
+```
+
+> **Platform note:** This publisher is macOS-only, depending on `DiskArbitration.framework`, `IOKit.framework`, and `CoreServices.framework`.
\ No newline at end of file
diff --git a/osquery/events/darwin/.endpointsecurity.md b/osquery/events/darwin/.endpointsecurity.md
index 4e48c562096..787613e5224 100644
--- a/osquery/events/darwin/.endpointsecurity.md
+++ b/osquery/events/darwin/.endpointsecurity.md
@@ -1,26 +1,26 @@
-macOS Endpoint Security event publisher and subscriber definitions for osquery, providing process and file system monitoring via Apple's EndpointSecurity framework (requires macOS 10.15+).
+macOS Endpoint Security event publisher and subscriber definitions for osquery, providing process and file system event monitoring via Apple's EndpointSecurity framework (requires macOS 10.15+).
## Key Components
-### Context Structs
+### Subscription & Event Context Structs
| Struct | Purpose |
|---|---|
-| `EndpointSecuritySubscriptionContext` | Holds ES event type subscriptions and row buffer for process events |
-| `EndpointSecurityEventContext` | Full process event payload β PID, credentials, code signing, exec args, fork/exit data |
-| `EndpointSecurityFileSubscriptionContext` | Holds ES event type subscriptions and row buffer for file events |
-| `EndpointSecurityFileEventContext` | Extends process context with `filename` and `dest_filename` for file operations |
+| `EndpointSecuritySubscriptionContext` | Holds process event type subscriptions and accumulated rows |
+| `EndpointSecurityEventContext` | Rich process event data: PID, credentials, codesigning, exec args, fork/exit info |
+| `EndpointSecurityFileSubscriptionContext` | Holds file event type subscriptions and accumulated rows |
+| `EndpointSecurityFileEventContext` | Extends process context with source/destination filename fields |
### Publishers
-- **`EndpointSecurityPublisher`** β Registers as `"endpointsecurity"`, manages an `es_client_s*` handle, dispatches process-level ES events (`exec`, `fork`, `exit`) to subscribers
-- **`EndpointSecurityFileEventPublisher`** β Registers as `"endpointsecurity_fim"`, manages a separate `es_file_client_s*` handle with configurable path muting/filtering for file integrity monitoring (FIM); ships with a default muted path list covering high-noise system daemons (e.g., `WindowServer`, `tccd`, `securityd`)
+- **`EndpointSecurityPublisher`** β Manages an `es_client_s` connection, dispatches process-level ES events (`exec`, `fork`, `exit`) to subscribers. Publisher name: `"endpointsecurity"`.
+- **`EndpointSecurityFileEventPublisher`** β Manages a separate `es_file_client_s` connection for file integrity monitoring (FIM). Supports path muting, prefix exclusions, and ships with a default muted list of high-noise Apple system processes. Publisher name: `"endpointsecurity_fim"`.
### Subscribers
-- **`ESProcessEventSubscriber`** β Subscribes to `EndpointSecurityPublisher`, populates the `es_process_events` osquery table
-- **`ESProcessFileEventSubscriber`** β Subscribes to `EndpointSecurityFileEventPublisher`, populates the `es_process_file_events` osquery table
+- **`ESProcessEventSubscriber`** β Subscribes to `EndpointSecurityPublisher`; populates the `es_process_events` table.
+- **`ESProcessFileEventSubscriber`** β Subscribes to `EndpointSecurityFileEventPublisher`; populates the `es_process_file_events` table.
## Usage Example
@@ -40,10 +40,14 @@ class MyProcessSubscriber
Status Callback(const EndpointSecurityEventContextRef& ec,
const EndpointSecuritySubscriptionContextRef& sc) {
- // Access ec->pid, ec->path, ec->args, ec->signing_id, etc.
+ Row r;
+ r["pid"] = INTEGER(ec->pid);
+ r["path"] = ec->path;
+ r["args"] = ec->args;
+ addRow(r);
return Status::success();
}
};
```
-> **Platform note:** All publisher and subscriber methods are gated with `API_AVAILABLE(macos(10.15))`. This header has no effect on non-macOS builds.
\ No newline at end of file
+> **Note:** All publisher and subscriber methods are gated with `API_AVAILABLE(macos(10.15))`. This header is macOS-only and requires the `EndpointSecurity.framework` entitlement at runtime.
\ No newline at end of file
diff --git a/osquery/events/darwin/.es_utils.md b/osquery/events/darwin/.es_utils.md
index ee9049cde42..a038335a34e 100644
--- a/osquery/events/darwin/.es_utils.md
+++ b/osquery/events/darwin/.es_utils.md
@@ -1,26 +1,32 @@
-Utility header for extracting and formatting process and string properties from macOS Endpoint Security (`es_*`) data structures within the osquery framework.
+Utility header providing helper functions for extracting and formatting data from Apple's Endpoint Security framework (`es_*`) types within the osquery event pipeline.
## Key Components
| Function | Description |
|---|---|
-| `getEsNewClientErrorMessage` | Converts an `es_new_client_result_t` error code into a human-readable string |
-| `getPath` | Extracts the executable path from an `es_process_t` process struct |
+| `getEsNewClientErrorMessage` | Converts `es_new_client_result_t` error codes to human-readable strings |
+| `getPath` | Extracts the executable path from an `es_process_t` struct |
| `getSigningId` | Retrieves the code-signing identifier from an `es_process_t` |
| `getTeamId` | Retrieves the Apple Developer Team ID from an `es_process_t` |
-| `getStringFromToken` | Converts a mutable or const `es_string_token_t` to a `std::string` |
-| `getCwdPathFromPid` | Resolves the current working directory path for a given PID |
-| `getCDHash` | Extracts the code-directory hash from an `es_process_t` |
-| `getProcessProperties` | Populates an `EndpointSecurityEventContextRef` with properties from a process |
-| `appendQuotedString` | Appends a delimiter-quoted string to an output stream |
+| `getStringFromToken` | Converts `es_string_token_t` (mutable and const overloads) to `std::string` |
+| `getCwdPathFromPid` | Resolves the current working directory for a given PID |
+| `getCDHash` | Extracts the CDHash (code directory hash) from an `es_process_t` |
+| `getProcessProperties` | Populates an `EndpointSecurityEventContextRef` with properties from an `es_process_t` |
+| `appendQuotedString` | Writes a delimiter-quoted string to an output stream |
## Usage Example
-```c
+```cpp
#include
-// Inside an Endpoint Security event handler:
+// Handling a new ES client creation failure
+es_new_client_result_t result = es_new_client(&client, handler);
+if (result != ES_NEW_CLIENT_RESULT_SUCCESS) {
+ LOG(ERROR) << getEsNewClientErrorMessage(result);
+}
+
+// Extracting process metadata from an ES event
void handleEvent(const es_message_t* msg) {
const es_process_t* proc = msg->process;
@@ -28,13 +34,16 @@ void handleEvent(const es_message_t* msg) {
std::string signingId = osquery::getSigningId(proc);
std::string teamId = osquery::getTeamId(proc);
std::string cdHash = osquery::getCDHash(proc);
- std::string cwd = osquery::getCwdPathFromPid(audit_token_to_pid(proc->audit_token));
+ std::string cwd = osquery::getCwdPathFromPid(
+ audit_token_to_pid(proc->audit_token));
+ // Populate event context
osquery::getProcessProperties(proc, eventContext);
-
- std::ostringstream out;
- osquery::appendQuotedString(out, path, '"');
}
```
-> **Note:** This header is macOS-only and depends on the Apple Endpoint Security framework (`es_process_t`, `es_string_token_t`). It is used internally by osquery's EndpointSecurity event publisher to normalize raw ES API types into standard C++ types before query processing.
\ No newline at end of file
+## Notes
+
+- macOS-only; depends on the `EndpointSecurity` framework
+- All functions live in the `osquery` namespace
+- `getStringFromToken` provides both `const` and non-`const` overloads for `es_string_token_t`
\ No newline at end of file
diff --git a/osquery/events/darwin/.event_taps.md b/osquery/events/darwin/.event_taps.md
index f8b09845338..efecafbc510 100644
--- a/osquery/events/darwin/.event_taps.md
+++ b/osquery/events/darwin/.event_taps.md
@@ -1,46 +1,45 @@
-macOS event tap publisher that monitors and intercepts system-level input events (keyboard, mouse, etc.) using the CoreGraphics `CGEventTap` API, exposing them to osquery subscribers.
+macOS event tap publisher that captures and dispatches system-level input events (keyboard, mouse, etc.) using the Core Graphics Event Services API.
## Key Components
| Symbol | Type | Description |
-|---|---|---|
+|--------|------|-------------|
| `EventTappingSubscriptionContext` | Struct | Empty subscription context for event tap subscriptions |
-| `EventTappingEventContext` | Struct | Empty event context carrying tapped event data |
-| `EventTappingEventPublisher` | Class | Core publisher managing the CGEventTap lifecycle and run loop |
-| `EventTappingConsumerRunner` | Class (forward) | Dispatched service that processes published event tap events |
+| `EventTappingEventContext` | Struct | Empty event context carrying dispatched tap events |
+| `EventTappingEventPublisher` | Class | Publisher that installs a CGEvent tap and fires osquery events |
+| `EventTappingConsumerRunner` | Class (fwd) | Dispatched service that processes published tap events |
-### `EventTappingEventPublisher` Methods
+## Key Methods
| Method | Description |
-|---|---|
-| `setUp()` | Initializes the CGEventTap and run loop source |
-| `tearDown()` | Cleans up tap resources |
-| `stop()` | Stops the run loop |
-| `run()` | Starts the publisher run loop |
-| `restart()` | Reinitializes the event tap (e.g., after system re-enables it) |
-| `eventCallback()` | Static CGEventTap callback receiving raw `CGEventRef` events |
+|--------|-------------|
+| `setUp()` | Installs the CGEvent tap and run loop source |
+| `tearDown()` / `stop()` | Cleans up the tap, run loop source, and Mach port |
+| `run()` | Enters the CFRunLoop to receive events |
+| `restart()` | Re-enables the tap if it becomes disabled |
+| `eventCallback()` | Static CGEvent tap callback; fires subscriber events |
| `shouldFire()` | Filters events against subscription context |
## Usage Example
```cpp
-// Subscribing to event tap events in an osquery EventSubscriber
+// Subscribing to macOS event tap events
class MyEventTapSubscriber
: public EventSubscriber {
public:
Status init() override {
auto sc = createSubscriptionContext();
- subscribe(&MyEventTapSubscriber::onEvent, sc);
+ subscribe(&MyEventTapSubscriber::handleEvent, sc);
return Status::success();
}
- Status onEvent(const EventTappingEventContextRef& ec,
- const EventTappingSubscriptionContextRef& sc) {
- // Process intercepted macOS input event
+ Status handleEvent(const EventTappingEventContextRef& ec,
+ const EventTappingSubscriptionContextRef& sc) {
+ // Process captured macOS input events here
return Status::success();
}
};
```
-> **Note:** This publisher is macOS-only and requires the `ApplicationServices` framework. The process may need Accessibility permissions (`TCC`) for the event tap to function correctly in macOS 10.15+.
\ No newline at end of file
+> **Note:** Requires `com.apple.security.temporary-exception.mach-lookup.global-name` entitlement or Accessibility permissions on macOS. The publisher uses a `CFRunLoop` with a `CFMachPortRef`-backed tap; the tap may be automatically disabled by the OS if the callback is too slow.
\ No newline at end of file
diff --git a/osquery/events/darwin/.fsevents.md b/osquery/events/darwin/.fsevents.md
index 68064e595fb..f14636ebfc8 100644
--- a/osquery/events/darwin/.fsevents.md
+++ b/osquery/events/darwin/.fsevents.md
@@ -1,47 +1,51 @@
-Wraps Apple's FSEvents API as an osquery `EventPublisher`, enabling filesystem change monitoring with path globbing, recursive watching, and event filtering on macOS.
+Defines the macOS FSEvents event publisher for osquery, wrapping Apple's `FSEventStreamRef` API to deliver filesystem change notifications to subscribers.
## Key Components
### `FSEventsSubscriptionContext`
-Defines what to watch:
-- `path` β filesystem path to monitor (supports glob wildcards)
+Subscription configuration struct containing:
+- `path` β filesystem path to watch
- `mask` β optional `FSEventStreamEventFlags` filter
-- `recursive` β enables recursive directory watching
-- `category` β config-originated category label
+- `recursive` β whether the watch is recursive
+- `category` β config category origin
- `requireAction()` β appends a required action filter
-- Private fields `discovered_` and `recursive_match` used internally by the publisher for path resolution and event matching
+- Private fields `discovered_` and `recursive_match` used internally by the publisher for glob/wildcard resolution
### `FSEventsEventContext`
-Carries data for a fired event:
+Event data struct populated on each filesystem event:
- `fsevent_stream`, `fsevent_flags`, `transaction_id` β raw FSEvents metadata
-- `path`, `action` β resolved path and human-readable action string
+- `path`, `action` β resolved path and action string
### `FSEventsEventPublisher`
Core publisher class inheriting `EventPublisher`:
-| Method | Purpose |
+| Method | Description |
|---|---|
-| `configure()` | Rebuilds watch paths and exclude sets on config change |
-| `run()` | Starts the CFRunLoop-based event loop |
-| `tearDown()` / `stop()` | Stops the stream and cleans up |
-| `Callback()` | Static FSEvents client callback; fires event contexts |
-| `shouldFire()` | Filters events against subscription criteria |
+| `configure()` | Rebuilds watched path set on config load/update |
+| `run()` | Starts the `CFRunLoop` entrypoint |
+| `tearDown()` / `stop()` | Stops stream and run loop |
+| `Callback()` | Static FSEvents client callback receiving raw kernel events |
+| `shouldFire()` | Filters events against subscription context |
| `transformSubscription()` | Resolves globs/wildcards at configure time |
-| `buildExcludePathsSet()` | Populates `ExcludePathSet` for suppressed paths |
+| `buildExcludePathsSet()` | Populates `ExcludePathSet` from config exclusions |
+| `flush()` | Forces flush of kernel-buffered events |
+
+### Type Aliases
+- `FSEventsEventContextRef` β `std::shared_ptr`
+- `FSEventsSubscriptionContextRef` β `std::shared_ptr`
+- `ExcludePathSet` β `PathSet` for exclusion matching
## Usage Example
```cpp
-// Subscribe to all changes under /etc recursively
+// Register a subscription to watch /etc recursively
auto sc = std::make_shared();
-sc->path = "/etc";
+sc->path = "/etc";
sc->recursive = true;
-sc->category = "config_files";
-sc->requireAction("UPDATED");
-
-// The publisher matches fired events against this context via shouldFire()
-// and delivers FSEventsEventContext to the subscriber callback
-```
+sc->category = "fim";
+sc->requireAction("CREATED");
-> **Note:** This publisher is macOS-only and requires `CoreServices.framework`. Path inputs should use filesystem glob syntax (e.g., `**`), not SQL wildcards.
\ No newline at end of file
+// The publisher resolves globs, starts the CFRunLoop stream,
+// and calls shouldFire() before dispatching to subscribers.
+```
\ No newline at end of file
diff --git a/osquery/events/darwin/.iokit.md b/osquery/events/darwin/.iokit.md
index d99f0934fde..9eb46eefaf3 100644
--- a/osquery/events/darwin/.iokit.md
+++ b/osquery/events/darwin/.iokit.md
@@ -1,57 +1,54 @@
-Provides the `IOKitEventPublisher` class and associated context structures for subscribing to and handling macOS IOKit hardware device attach/detach events within the osquery event framework.
+Provides the `IOKitEventPublisher` class and supporting types for monitoring macOS IOKit hardware device attach/detach events within the osquery event framework.
## Key Components
-### Structs
+**Structs**
+- `IOKitSubscriptionContext` β Filter criteria for event subscriptions; holds `model_id`, `vendor_id`, and bus `type` (e.g., `"USB"`)
+- `IOKitEventContext` β Event payload describing a device event; includes `action`, `type`, `vendor`, `model`, `path`, `driver`, `version`, and `serial`
+- `DeviceTracker` β Internal struct tracking active device detach notifications
-| Struct | Description |
-|---|---|
-| `IOKitSubscriptionContext` | Subscription filter with `model_id`, `vendor_id`, and bus `type` (e.g., `"USB"`) |
-| `IOKitEventContext` | Event payload carrying device metadata: `action`, `vendor`, `model`, `path`, `driver`, `version`, `serial` |
-
-### Enums
-
-- **`IOKitEventContext::Action`** β `DEVICE_ATTACH (0)` or `DEVICE_DETACH`
-
-### Type Aliases
+**Enums**
+- `IOKitEventContext::Action` β `DEVICE_ATTACH` (`0`) or `DEVICE_DETACH`
+**Type Aliases**
- `IOKitEventContextRef` β `std::shared_ptr`
- `IOKitSubscriptionContextRef` β `std::shared_ptr`
-### Class: `IOKitEventPublisher`
-
-Extends `EventPublisher`. Manages a `CFRunLoop` and `IONotificationPort` to listen for IOKit device notifications.
+**Class: `IOKitEventPublisher`**
+Extends `EventPublisher`; manages a `CFRunLoop` and `IONotificationPort` to receive kernel-level device notifications.
| Method | Description |
|---|---|
-| `run()` | Starts the CFRunLoop and notification monitoring |
-| `tearDown()` | Cleans up run loop and IOKit resources |
-| `shouldFire()` | Filters events against subscription context |
-| `deviceAttach()` *(static)* | IOKit callback for device connect events |
-| `deviceDetach()` *(static)* | IOKit callback for device disconnect events |
+| `run()` | Starts the `CFRunLoop`; blocks until stopped |
+| `tearDown()` | Cleans up IOKit resources |
+| `shouldFire()` | Filters events against subscription criteria |
+| `deviceAttach()` | Static IOKit callback for device connect |
+| `deviceDetach()` | Static IOKit callback for device disconnect |
| `newEvent()` | Constructs and fires an `IOKitEventContext` |
-| `restart()` | Resets the run loop and re-registers notifications |
+| `restart()` | Resets the run loop and notification port |
## Usage Example
```cpp
// Subscribe to USB device events
auto sc = std::make_shared();
-sc->type = "USB";
+sc->type = "USB";
sc->vendor_id = "05ac"; // Apple vendor ID
EventFactory::addSubscription(
"iokit",
- Subscription::create("usb_monitor", sc,
- [](const EventContextRef& ec, const void*) {
- auto event = std::static_pointer_cast(ec);
- if (event->action == IOKitEventContext::DEVICE_ATTACH) {
- LOG(INFO) << "Device attached: " << event->model
- << " path=" << event->path;
- }
- })
+ Subscription::create("my_usb_table", sc, callback)
);
+
+// Event callback receives IOKitEventContextRef
+void callback(const IOKitEventContextRef& ec,
+ const IOKitSubscriptionContextRef& sc) {
+ if (ec->action == IOKitEventContext::DEVICE_ATTACH) {
+ LOG(INFO) << "Device attached: " << ec->model
+ << " path=" << ec->path;
+ }
+}
```
-> **Note:** `publisher_started_` is intentionally set `false` during initial iterator seeding to suppress synthetic attach events at startup β only real plug/unplug events are emitted after `restart()` completes.
\ No newline at end of file
+> **Note:** `publisher_started_` is intentionally `false` during the initial IOKit iterator seed walk to suppress spurious attach events at startup.
\ No newline at end of file
diff --git a/osquery/events/darwin/.openbsm.md b/osquery/events/darwin/.openbsm.md
index 4e4167c36be..63af49d76af 100644
--- a/osquery/events/darwin/.openbsm.md
+++ b/osquery/events/darwin/.openbsm.md
@@ -1,37 +1,49 @@
-Defines the OpenBSM event publisher and associated context structures for subscribing to and processing macOS/BSD audit log events within the osquery eventing framework.
+Header file defining the OpenBSM audit event publisher for osquery, enabling subscription-based monitoring of macOS/BSD kernel audit events via the OpenBSM audit pipe.
## Key Components
-| Name | Type | Description |
-|---|---|---|
-| `OpenBSMSubscriptionContext` | Struct | Holds the `event_id` a subscriber wants to monitor (e.g., `23` for `execve`) |
-| `OpenBSMEventContext` | Struct | Carries a fired event's `event_id`, parsed `tokenstr_t` tokens, and a shared memory buffer |
-| `OpenBSMEventContextRef` | Type alias | `std::shared_ptr` |
-| `OpenBSMSubscriptionContextRef` | Type alias | `std::shared_ptr` |
-| `OpenBSMEventPublisher` | Class | Core publisher that reads from the audit pipe, filters events by subscribed IDs, and fires matching event contexts |
+### Structs
-### `OpenBSMEventPublisher` Methods
+- **`OpenBSMSubscriptionContext`** β Subscription filter containing `event_id` (e.g., `23` for `execve`) to match specific audit event types
+- **`OpenBSMEventContext`** β Event payload carrying `event_id`, a vector of parsed `tokenstr_t` tokens, and a managed `buffer` pointer to raw OpenBSM memory
-| Method | Description |
+### Type Aliases
+
+- **`OpenBSMEventContextRef`** β `std::shared_ptr`
+- **`OpenBSMSubscriptionContextRef`** β `std::shared_ptr`
+
+### Classes
+
+- **`OpenBSMEventPublisher`** β Core publisher implementing the osquery `EventPublisher` interface. Manages the audit pipe lifecycle and dispatches matching events to subscribers.
+
+| Method | Purpose |
|---|---|
-| `setUp()` | Initializes the publisher |
+| `setUp()` | Initializes the audit pipe connection |
| `configure()` | Rebuilds the set of subscribed event IDs |
-| `tearDown()` | Closes the audit pipe and cleans up resources |
-| `run()` | Polling loop β reads audit records until interrupted |
-| `acquireMessages()` | Dequeues and parses raw records from the audit pipe |
-| `configureAuditPipe()` | Opens and configures `/dev/auditpipe` |
-| `shouldFire()` | Matches incoming events against subscription contexts |
+| `tearDown()` | Closes the audit pipe and cleans up |
+| `run()` | Polling loop β reads from the audit descriptor until interrupted |
+| `shouldFire()` | Filters events against active subscriptions |
## Usage Example
```c
-// Subscribe to execve events (event_id = 23)
+// Define a subscriber for execve events (event_id = 23)
auto sub_ctx = std::make_shared();
sub_ctx->event_id = 23;
-// Register the subscription β the publisher handles routing
-EventFactory::addSubscription("openbsm", sub_ctx, callback);
+// Subscribe and handle incoming events
+EventFactory::addSubscription(
+ "openbsm",
+ Subscription::create("my_subscriber", sub_ctx, callback));
+
+// In the callback, access parsed tokens
+void callback(const OpenBSMEventContextRef& ec,
+ const OpenBSMSubscriptionContextRef& sc) {
+ for (const auto& token : ec->tokens) {
+ // Process each OpenBSM audit token
+ }
+}
```
-> **Note:** `OpenBSMEventPublisher` is a dispatched service β `run()` is called by the osquery eventing thread, not directly by subscribers. Access to `audit_pipe_` and `event_ids_` is guarded by dedicated `Mutex` members.
\ No newline at end of file
+> **Note:** `OpenBSMEventPublisher` runs as a dispatched service (`OpenBSMConsumerRunner`) and is thread-safe via `Mutex` guards on both the audit pipe and event ID set.
\ No newline at end of file
diff --git a/osquery/events/darwin/.scnetwork.md b/osquery/events/darwin/.scnetwork.md
index 4f5dc1b2f1c..5a99fba90d9 100644
--- a/osquery/events/darwin/.scnetwork.md
+++ b/osquery/events/darwin/.scnetwork.md
@@ -3,44 +3,39 @@ Provides the osquery event publisher interface for monitoring macOS network reac
## Key Components
-### Enumerations
-
-- **`SCNetworkSubscriptionType`** β Defines target types: `ADDRESS_TARGET` (IP address) or `NAME_TARGET` (hostname)
+### Enums
+- **`SCNetworkSubscriptionType`** β Distinguishes between `ADDRESS_TARGET` (IP-based) and `NAME_TARGET` (hostname-based) reachability targets.
### Structs
-
-- **`SCNetworkSubscriptionContext`** β Subscription configuration containing target type, hostname/address string, address family, and a reachability flags bitmask filter
-- **`SCNetworkEventContext`** β Event payload carrying the originating subscription context and observed `SCNetworkReachabilityFlags`
+- **`SCNetworkSubscriptionContext`** β Subscription configuration holding the target type, hostname/address string, address family, and an optional reachability flags bitmask (`mask`) to filter events.
+- **`SCNetworkEventContext`** β Event payload carrying the triggering subscription reference and the current `SCNetworkReachabilityFlags` at the time of the callback.
### Class: `SCNetworkEventPublisher`
-
-An `EventPublisher` subclass registered under the `"scnetwork"` identifier. Manages a CoreFoundation run loop with registered reachability targets.
+An `EventPublisher` that wraps the macOS `SCNetworkReachability` run-loop callback model.
| Method | Description |
|---|---|
-| `configure()` | Rebuilds and registers reachability targets |
-| `run()` | Starts the CFRunLoop for async callbacks |
-| `tearDown()` | Cleans up all registered targets |
-| `shouldFire()` | Filters events against subscription flag masks |
-| `Callback()` (static) | SCNetwork callback invoked on reachability change |
-| `addHostname()` / `addAddress()` | Register name or address targets |
-| `clearAll()` | Removes all tracked targets and contexts |
+| `configure()` | Rebuilds reachability targets from active subscriptions |
+| `setUp()` | Returns a disabled status (publisher is callback-driven, not polled) |
+| `tearDown()` | Releases all targets and stops monitoring |
+| `run()` | Enters the `CFRunLoop` for the publisher thread |
+| `Callback()` *(static)* | SCNetwork callback invoked on reachability flag changes |
+| `shouldFire()` | Filters events against the subscription's flag mask |
+| `addHostname()` / `addAddress()` | Register hostname or IP targets with SCNetwork |
+| `clearAll()` | Releases and removes all registered reachability targets |
## Usage Example
```cpp
-// Define a subscription context to monitor a hostname
+// Define a subscription watching a hostname for reachability changes
auto sc = std::make_shared();
-sc->type = NAME_TARGET;
-sc->target = "example.com";
+sc->type = SCNetworkSubscriptionType::NAME_TARGET;
+sc->target = "api.example.com";
sc->mask = kSCNetworkReachabilityFlagsReachable;
-// Subscribe an event subscriber using this context
-auto sub = EventFactory::createSubscription("scnetwork", sc);
+// Subscribe an EventSubscriber to the publisher
+auto subscription = SCNetworkEventPublisher::createSubscriptionContext();
+EventFactory::addSubscription("scnetwork", subscription);
```
-## Notes
-
-- macOS-only; requires `SystemConfiguration.framework`
-- `setUp()` always returns `Status(1, "Publisher not used")` β publisher lifecycle is driven by `configure()` and `run()`
-- Internal state is protected by a `Mutex` for thread-safe target management
\ No newline at end of file
+> **Note:** `setUp()` intentionally returns a failure status β this publisher relies entirely on Apple's `SCNetworkReachability` callback mechanism rather than a polling loop, so it is configured via `configure()` and driven by `CFRunLoop`.
\ No newline at end of file
diff --git a/osquery/events/linux/.auditdnetlink.md b/osquery/events/linux/.auditdnetlink.md
index d1fb75c544f..0c935cba3a0 100644
--- a/osquery/events/linux/.auditdnetlink.md
+++ b/osquery/events/linux/.auditdnetlink.md
@@ -1,43 +1,43 @@
-Header file defining the audit netlink interface for osquery's Linux audit subsystem integration, providing classes and data structures for reading, parsing, and consuming kernel audit events via the Linux netlink socket.
+Header defining the audit netlink interface for osquery's Linux audit subsystem integration, providing structures and services for reading, parsing, and accessing kernel audit events via the Netlink socket.
## Key Components
### Enums & Type Aliases
-- **`NetlinkStatus`** β Enum indicating netlink handle state: `ActiveMutable`, `ActiveImmutable`, `Disabled`, or `Error`
-- **`AuditRuleDataObject`** β `std::vector` wrapping raw audit rule data
-- **`AuditdContextRef`** β `shared_ptr` for shared ownership across services
+- **`NetlinkStatus`** β Enum indicating handle state: `ActiveMutable`, `ActiveImmutable`, `Disabled`, `Error`
+- **`AuditRuleDataObject`** β `std::vector` wrapping raw `audit_rule_data`
+- **`AuditdContextRef`** β `shared_ptr` for shared ownership between services
### Structs
-- **`AuditEventRecord`** β A parsed audit event containing type, timestamp, audit ID, key-value fields, and raw message data
-- **`AuditdContext`** β Thread-safe shared state between reader and parser services; holds unprocessed/processed queues, mutexes, condition variables, and throttling counters
+- **`AuditEventRecord`** β A parsed audit record containing `type`, `time`, `audit_id`, `fields` map, and `raw_data` for SELinux/AppArmor records
+- **`AuditdContext`** β Thread-safe shared state between reader and parser services, holding unprocessed/processed queues, mutexes, condition variables, and throttling counters
### Classes
-- **`AuditdNetlinkReader`** β `InternalRunnable` service that acquires the netlink handle, configures audit rules, reads raw `audit_reply` records, and manages audit service lifecycle
-- **`AuditdNetlinkParser`** β `InternalRunnable` service that parses raw `audit_reply` structures into `AuditEventRecord` objects; exposes static `ParseAuditReply()` and `AdjustAuditReply()` utilities
-- **`AuditdNetlink`** β Top-level consumer interface; calls `getEvents()` to retrieve fully processed `AuditEventRecord` vectors
+- **`AuditdNetlinkReader`** (`InternalRunnable`) β Background service that acquires the netlink handle, configures audit rules, reads raw `audit_reply` messages, and manages rule lifecycle
+- **`AuditdNetlinkParser`** (`InternalRunnable`) β Background service that parses raw `audit_reply` structs into `AuditEventRecord` objects; exposes static `ParseAuditReply()` and `AdjustAuditReply()` helpers
+- **`AuditdNetlink`** β Public-facing, non-copyable consumer class; call `getEvents()` to drain processed records
-### Utility
-- **`DecodeAuditPathValues()`** β Inline function that strips surrounding quotes or hex-decodes audit field values using `boost::algorithm::unhex`
+### Inline Utility
+- **`DecodeAuditPathValues()`** β Strips surrounding quotes or hex-decodes audit field values via Boost
## Usage Example
```cpp
#include "auditdnetlink.h"
-// Initialize shared context and the top-level netlink interface
+// Instantiate the netlink interface (starts reader/parser internally)
osquery::AuditdNetlink netlink;
-// Poll for new audit events in a publisher loop
+// Poll for parsed audit events in a publisher loop
while (running) {
- std::vector events = netlink.getEvents();
- for (const auto& record : events) {
- // Access parsed fields
- auto it = record.fields.find("exe");
- if (it != record.fields.end()) {
- std::string exe = osquery::DecodeAuditPathValues(it->second);
- // process exe path...
+ auto events = netlink.getEvents();
+ for (const auto& record : events) {
+ // record.type -> AUDIT_SYSCALL, AUDIT_PATH, etc.
+ // record.fields -> key/value pairs from the audit record
+ auto path_it = record.fields.find("name");
+ if (path_it != record.fields.end()) {
+ auto decoded = osquery::DecodeAuditPathValues(path_it->second);
+ }
}
- }
}
```
\ No newline at end of file
diff --git a/osquery/events/linux/.auditeventpublisher.md b/osquery/events/linux/.auditeventpublisher.md
index b3b36217a6a..3b3a3a080e4 100644
--- a/osquery/events/linux/.auditeventpublisher.md
+++ b/osquery/events/linux/.auditeventpublisher.md
@@ -1,60 +1,74 @@
-Header file defining the Linux audit event publisher for osquery, providing data structures and interfaces for processing kernel audit events including syscalls, AppArmor, SELinux, and seccomp notifications via the Linux Audit netlink subsystem.
+Defines the Linux audit event publisher for osquery, providing data structures and publisher logic to collect, parse, and dispatch kernel audit events (syscalls, user events, AppArmor, SELinux, and Seccomp) from the Linux audit subsystem via netlink.
## Key Components
### Event Data Structures
| Struct | Description |
-|---|---|
+|--------|-------------|
| `UserAuditEventData` | Holds a user-space audit event ID |
-| `SyscallAuditEventData` | Captures syscall metadata: PID, UID/GID sets, executable path, success status |
-| `AppArmorAuditEventData` | Key-value fields for AppArmor audit records (profile, operation, masks, etc.) |
-| `SeccompAuditEventData` | Key-value fields for seccomp audit records (arch, syscall, signal, instruction pointer, etc.) |
-| `AuditEvent` | Top-level event descriptor wrapping all event types via `boost::variant` with a raw `record_list` |
+| `SyscallAuditEventData` | Syscall metadata: PID, UID/GID sets, executable path, success flag |
+| `AppArmorAuditEventData` | AppArmor fields (profile, operation, capability, masks, etc.) |
+| `SeccompAuditEventData` | Seccomp fields (arch, syscall, signal, IP, compat mode, etc.) |
+| `AuditEvent` | Top-level event descriptor holding type enum + variant data + raw record list |
-### Publisher Infrastructure
+### Publisher & Context Types
-| Type | Description |
-|---|---|
-| `AuditEventPublisher` | Core `EventPublisher` subclass; manages netlink I/O, assembles audit records into events |
-| `AuditEventContext` | Carries a `vector` dispatched to subscribers |
-| `AuditSubscriptionContext` | Subscription handle (opaque; controlled by the publisher) |
-| `AuditTraceContext` | `map` tracking in-flight multi-record audit sequences |
+- **`AuditEventPublisher`** β Core publisher class; drives the netlink read loop (`run()`), assembles raw records into typed `AuditEvent` objects, and dispatches to subscribers
+- **`AuditSubscriptionContext`** / **`AuditEventContext`** β Standard osquery pub/sub context types; event context carries a `std::vector`
+- **`AuditTraceContext`** β `std::map` used to correlate multi-record audit sequences by event ID
-### Free Functions
+### Key Free Functions
| Function | Description |
-|---|---|
-| `ProcessEvents()` | Aggregates raw `AuditEventRecord` lists into typed `AuditEvent` objects |
-| `GetEventRecord()` | Extracts a record of a specific type from an `AuditEvent` |
-| `GetStringFieldFromMap()` | Safe string field lookup with default value |
-| `GetIntegerFieldFromMap()` | Safe integer field lookup with configurable base and default |
-| `CopyFieldFromMap()` | Copies a named field into an osquery `Row` |
+|----------|-------------|
+| `AuditEventPublisher::ProcessEvents()` | Aggregates raw `AuditEventRecord` lists into complete `AuditEvent` objects |
+| `GetEventRecord()` | Retrieves a record by type from an `AuditEvent` |
+| `GetStringFieldFromMap()` | Safe string field extraction from audit field maps |
+| `GetIntegerFieldFromMap()` | Safe integer field extraction with configurable base/default |
+| `CopyFieldFromMap()` | Copies a field directly into an osquery `Row` |
| `StripQuotes()` | Removes surrounding quotes from audit field values |
-| `parseSeccompEvent()` | Parses a raw seccomp record into `SeccompAuditEventData` |
+| `parseSeccompEvent()` | Parses a raw Seccomp record into `SeccompAuditEventData` |
## Usage Example
```cpp
-// Subscribing to audit events
-auto sub_ctx = AuditEventPublisher::createSubscriptionContext();
-EventFactory::addSubscription("auditeventpublisher", sub_ctx,
- [](const AuditEventContextRef& ctx, const AuditSubscriptionContextRef&) {
- for (const auto& event : ctx->audit_events) {
- if (event.type == AuditEvent::Type::Syscall) {
- const auto& data = boost::get(event.data);
- LOG(INFO) << "Syscall " << data.syscall_number
- << " by PID " << data.process_id
- << " exe: " << data.executable_path;
+// Subscribing to audit events in an osquery EventSubscriber
+void AuditMySubscriber::init() {
+ auto subscription_context =
+ createSubscriptionContext();
+
+ subscribe(&AuditMySubscriber::eventCallback, subscription_context);
+}
+
+Status AuditMySubscriber::eventCallback(
+ const AuditEventContextRef& context,
+ const AuditSubscriptionContextRef& /*subscription*/) {
+
+ for (const auto& audit_event : context->audit_events) {
+ if (audit_event.type == AuditEvent::Type::Syscall) {
+ const auto& data =
+ boost::get(audit_event.data);
+
+ Row row;
+ row["syscall"] = std::to_string(data.syscall_number);
+ row["pid"] = std::to_string(data.process_id);
+ row["executable"] = data.executable_path;
+ row["succeeded"] = data.succeeded ? "1" : "0";
+
+ // Extract additional fields from raw records
+ const auto* record =
+ GetEventRecord(audit_event, AUDIT_SYSCALL);
+ if (record != nullptr) {
+ std::string cwd;
+ GetStringFieldFromMap(cwd, record->fields, "cwd", "");
+ row["cwd"] = StripQuotes(cwd);
}
+
+ addRow(row);
}
- return Status::success();
- });
-
-// Assembling raw records into typed events (used internally / in tests)
-AuditEventContextRef ctx = std::make_shared();
-AuditTraceContext trace;
-std::set allowed_failures = {257}; // e.g. openat allowed to fail
-AuditEventPublisher::ProcessEvents(ctx, raw_records, trace, allowed_failures);
+ }
+ return Status::success();
+}
```
\ No newline at end of file
diff --git a/osquery/events/linux/.inotify.md b/osquery/events/linux/.inotify.md
index 920966d4189..48edb9f8365 100644
--- a/osquery/events/linux/.inotify.md
+++ b/osquery/events/linux/.inotify.md
@@ -1,44 +1,57 @@
-Linux `inotify`-based filesystem event publisher header for osquery, defining subscription contexts, event contexts, and the `INotifyEventPublisher` class used to monitor file and directory changes on Linux.
+Linux `inotify` filesystem event publisher interface for osquery, defining the subscription context, event context, and publisher class used to monitor file and directory changes via the kernel's inotify API.
## Key Components
-### Constants & Type Aliases
-- `kMaskActions` β maps `inotify` mask bits to human-readable action strings
-- `kFileDefaultMasks` / `kFileAccessMasks` β predefined `inotify` event mask sets
-- `PathDescriptorMap` / `DescriptorPathMap` β bidirectional path β watch descriptor lookup maps
-- `ExcludePathSet` β pattern-aware set of paths excluded from event propagation
+### Structs
-### `INotifySubscriptionContext`
-Subscription configuration struct holding the watched path, optional action mask, recursive flag, category label, and lazy-deletion marker. Provides `requireAction()` to map string action names to `inotify` bitmask values.
+- **`INotifySubscriptionContext`** β Subscription configuration for a watched path. Holds the target path, event mask, recursive flag, category, and internal descriptor/status-change-time maps. Provides `requireAction()` to map string action names to inotify mask bits.
+- **`INotifyEventContext`** β Carries a fired inotify event, including the raw `inotify_event` struct, resolved path string, action string, transaction ID, and a back-reference to the originating subscription context.
-### `INotifyEventContext`
-Event payload struct carrying the raw `inotify_event`, resolved path string, action string, transaction ID, and a reference back to the originating subscription context.
+### Type Aliases
-### `INotifyEventPublisher`
-Core publisher class (inherits `EventPublisher`) managing the `inotify` file descriptor lifecycle, watch descriptor bookkeeping, and event dispatch loop. Key methods:
-
-| Method | Purpose |
+| Alias | Underlying Type |
|---|---|
-| `setUp()` | Opens the `inotify` handle |
-| `configure()` | Applies updated subscriptions from config |
-| `run()` | Main event polling loop |
-| `addMonitor()` | Registers a path watch, optionally recursive |
-| `needMonitoring()` | Guards `addMonitor` using status-change time |
-| `removeMonitor()` | Unregisters a watch descriptor |
-| `shouldFire()` | Matches an event against a subscription's path/mask |
-| `handleOverflow()` | Recovers from `IN_Q_OVERFLOW` by increasing read batch size |
+| `PathDescriptorMap` | `std::map` |
+| `DescriptorPathMap` | `std::map` |
+| `DescriptorINotifySubCtxMap` | `std::map` |
+| `ExcludePathSet` | `PathSet` |
+
+### Class: `INotifyEventPublisher`
+
+Extends `EventPublisher`. Manages the inotify file descriptor lifecycle, watch descriptor bookkeeping, recursive directory monitoring, and event dispatch.
+
+**Key public methods:**
+
+- `setUp()` β Initializes the inotify handle
+- `configure()` β Applies updated config to active watches
+- `tearDown()` β Releases the inotify handle and cleans up
+- `run()` β Main event loop; reads and dispatches inotify events
+- `addSubscription()` β Deduplicates and registers a new subscription
+- `removeSubscriptions()` β Lazily marks subscriptions for removal
+
+**Key private methods:**
+
+- `addMonitor()` / `needMonitoring()` β Add inotify watches with optional recursive enumeration
+- `monitorSubscription()` β Resolves a subscription context to actual watches
+- `shouldFire()` β Matches an event against a subscription's path and mask
+- `buildExcludePathsSet()` β Populates the path exclusion set from config
+- `handleOverflow()` β Recovers from `IN_Q_OVERFLOW` by reading extra events
+
+### Global Constants
+
+- `kMaskActions` β Maps inotify mask bits to human-readable action strings
+- `kFileDefaultMasks` / `kFileAccessMasks` β Preset mask combinations for common monitoring scenarios
## Usage Example
```cpp
-// Subscribe to file creation events under a directory
+// Subscribe to write events on a directory
auto sc = std::make_shared();
-sc->path = "/etc/myapp/";
+sc->path = "/etc/";
sc->recursive = true;
-sc->requireAction("CREATED");
+sc->requireAction("UPDATED"); // sets IN_CLOSE_WRITE bit in mask
-// The publisher dispatches INotifyEventContext to matching subscribers
-// ec->path β absolute path of the affected file
-// ec->action β "CREATED", "UPDATED", "DELETED", etc.
+auto sub = Subscription::create("my_subscriber", sc, callback);
+EventFactory::addSubscription("inotify", sub);
```
\ No newline at end of file
diff --git a/osquery/events/linux/.socket_events.md b/osquery/events/linux/.socket_events.md
index e6e1e3b6741..06d333d269a 100644
--- a/osquery/events/linux/.socket_events.md
+++ b/osquery/events/linux/.socket_events.md
@@ -1,9 +1,9 @@
-Declares the interface for retrieving the set of system call numbers monitored by the socket events subsystem in osquery.
+Declares the interface for retrieving the set of system call identifiers monitored for socket-related events within the osquery event framework.
## Key Components
-- **`getSocketEventsSyscalls()`** β Returns a `std::set` containing the syscall numbers relevant to socket event monitoring (e.g., `connect`, `bind`, `accept`).
+- **`getSocketEventsSyscalls()`** β Returns a `std::set` containing the syscall numbers relevant to socket event monitoring (e.g., `socket`, `connect`, `bind`, `accept`).
## Usage Example
@@ -11,16 +11,12 @@ Declares the interface for retrieving the set of system call numbers monitored b
#include "socket_events.h"
#include
-// Retrieve all syscalls tracked for socket events
+// Retrieve syscalls tracked for socket events
std::set syscalls = osquery::getSocketEventsSyscalls();
-for (int syscall_nr : syscalls) {
- std::cout << "Monitoring syscall: " << syscall_nr << std::endl;
+for (int syscall : syscalls) {
+ std::cout << "Monitoring syscall: " << syscall << std::endl;
}
```
-## Notes
-
-- Lives within the `osquery` namespace.
-- Typically consumed by the audit-based event publisher to register which syscalls to subscribe to for network socket activity tracking.
-- The returned set drives kernel-level audit rule registration β only syscalls in this set will generate socket events in the osquery event pipeline.
\ No newline at end of file
+> **Note:** This header is typically used internally by osquery's audit-based event publishers to register the correct syscall filters when setting up socket activity monitoring on Linux systems.
\ No newline at end of file
diff --git a/osquery/events/linux/.syslog.md b/osquery/events/linux/.syslog.md
index cd8b52ae6e8..1bf0f1a58b9 100644
--- a/osquery/events/linux/.syslog.md
+++ b/osquery/events/linux/.syslog.md
@@ -1,25 +1,29 @@
-Declares the event publisher and supporting types for ingesting syslog entries forwarded from rsyslog via a named pipe, publishing parsed log fields to osquery subscribers.
+Defines the event publisher infrastructure for ingesting syslog entries forwarded through rsyslog, including context types, a non-blocking pipe reader, and a CSV tokenizer for rsyslog output.
## Key Components
-| Symbol | Type | Description |
-|---|---|---|
-| `SyslogSubscriptionContext` | struct | Empty subscription context; no filtering criteria needed |
-| `SyslogEventContext` | struct | Holds a syslog message as a `map` of parsed fields |
-| `NonBlockingFStream` | class | Non-blocking pipe reader with internal ring buffer; exposes `openReadOnly`, `getline`, and `close` |
-| `SyslogEventPublisher` | class | osquery event publisher; reads JSON syslog lines from a named pipe, parses them, and fires events |
-| `RsyslogCsvSeparator` | class | Boost `TokenizerFunction` functor that handles rsyslog's CSV dialect (`""` escaping, no backslash escaping) |
+### Structs
+- **`SyslogSubscriptionContext`** β Empty subscription context for syslog event filtering (reserved for future use)
+- **`SyslogEventContext`** β Holds a parsed syslog entry as a `map` of field name/value pairs
+
+### Classes
+- **`NonBlockingFStream`** β Non-blocking file stream wrapper over a raw file descriptor; buffers reads and exposes a `getline()` that returns immediately without blocking on a pipe. Default buffer size is 2048 bytes.
+- **`SyslogEventPublisher`** β Core event publisher that reads JSON syslog lines from a named pipe created for rsyslog forwarding. Manages pipe creation, exclusive locking, error thresholding, and event dispatch to subscribers.
+- **`RsyslogCsvSeparator`** β Boost `TokenizerFunction` functor that correctly parses rsyslog CSV output, handling rsyslog's `""` quote-escaping convention and no backslash escaping.
+
+### Type Aliases
+- `SyslogEventContextRef` β `shared_ptr`
+- `SyslogSubscriptionContextRef` β `shared_ptr`
## Usage Example
```cpp
-// Subscribing to syslog events in an EventSubscriber
+// Subscribing to syslog events
class MySyslogSubscriber
: public EventSubscriber {
public:
Status init() override {
- // No filter criteria needed; SyslogSubscriptionContext is empty
auto sc = createSubscriptionContext();
subscribe(&MySyslogSubscriber::onEvent, sc);
return Status::success();
@@ -30,11 +34,19 @@ class MySyslogSubscriber
// Access parsed syslog fields
auto it = ec->fields.find("message");
if (it != ec->fields.end()) {
- LOG(INFO) << "syslog message: " << it->second;
+ LOG(INFO) << "Syslog message: " << it->second;
}
return Status::success();
}
};
+
+// Non-blocking pipe read (used internally by SyslogEventPublisher)
+NonBlockingFStream stream;
+stream.openReadOnly("/var/osquery/syslog.pipe");
+std::string line;
+if (stream.getline(line).ok()) {
+ // process complete line
+}
```
-> **Note:** `SyslogEventPublisher` requires rsyslog to be configured to write JSON-formatted entries to the named pipe path defined in osquery's configuration. Only the first osquery process to acquire the pipe lock (`lockPipe`) will consume events; subsequent processes (e.g. `osqueryi`) are silently skipped to avoid corrupting `osqueryd` reads.
\ No newline at end of file
+> **Note:** rsyslog must be configured to forward JSON-formatted syslog entries to the named pipe path that `SyslogEventPublisher` monitors. Only the first osquery process to acquire the pipe lock will be permitted to read, preventing conflicts between `osqueryd` and `osqueryi` instances.
\ No newline at end of file
diff --git a/osquery/events/linux/.udev.md b/osquery/events/linux/.udev.md
index 2dcfc678f43..487922414c6 100644
--- a/osquery/events/linux/.udev.md
+++ b/osquery/events/linux/.udev.md
@@ -1,49 +1,44 @@
-Defines the Linux `udev` event publisher interface for osquery, enabling subscribers to monitor hardware device events (add, remove, change) via the `libudev` API.
+Defines the Linux `udev` event publisher interface for osquery, enabling subscribers to monitor hardware device events (add, remove, change) via the kernel's udev subsystem.
## Key Components
-### Enums
-- **`udev_event_action`** β Device event types: `ADD`, `REMOVE`, `CHANGE`, `UNKNOWN`, and `ALL` (subscriber catch-all)
+**Enums**
+- `udev_event_action` β Device event action types: `ADD`, `REMOVE`, `CHANGE`, `UNKNOWN`, and `ALL` (subscriber catch-all)
-### Structs
-- **`UdevSubscriptionContext`** β Subscription filter criteria; restrict events by `action`, `subsystem`, `devnode`, `devtype`, or `driver`
-- **`UdevEventContext`** β Fired event payload carrying a `udev_device*` pointer, resolved `action`, and device metadata strings
+**Structs**
+- `UdevSubscriptionContext` β Subscription filter criteria: action, subsystem, devnode, devtype, and driver
+- `UdevEventContext` β Event payload: raw `udev_device*` pointer, action enum + string, subsystem, devnode, devtype, and driver
-### Type Aliases
-- **`UdevEventContextRef`** β `std::shared_ptr`
-- **`UdevSubscriptionContextRef`** β `std::shared_ptr`
-
-### Class: `UdevEventPublisher`
-Extends `EventPublisher` and manages the udev socket monitor lifecycle.
+**Type Aliases**
+- `UdevEventContextRef` β `std::shared_ptr`
+- `UdevSubscriptionContextRef` β `std::shared_ptr`
+**Class: `UdevEventPublisher`**
| Method | Description |
|---|---|
| `setUp()` | Initializes the udev handle and monitor |
| `tearDown()` | Releases udev resources |
-| `run()` | Polls the monitor and dispatches events |
-| `getValue(device, property)` | Returns a udev property string |
-| `getAttr(device, attr)` | Returns a udev sysattr string |
-| `shouldFire(...)` | Filters events against subscription context |
+| `run()` | Event loop β polls udev monitor socket |
+| `getValue(device, property)` | Returns a udev property string value |
+| `getAttr(device, attr)` | Returns a udev sysattr string value |
+| `shouldFire(...)` | Matches incoming events against subscription filters |
| `createEventContextFrom(device)` | Builds an `UdevEventContextRef` from a raw device pointer |
## Usage Example
```cpp
-// Create a subscription context filtering USB add events
-auto sc = createSubscriptionContext();
+// Define a subscription context to watch USB block device additions
+auto sc = std::make_shared();
sc->action = UDEV_EVENT_ACTION_ADD;
sc->subsystem = "usb";
-
-// Subscribe with a callback
-subscribe(&MySubscriber::onUsbAdd, sc);
-
-// In the callback, inspect event context
-void onUsbAdd(const UdevEventContextRef& ec) {
- auto node = ec->devnode; // e.g. "/dev/bus/usb/001/002"
- auto driver = ec->driver;
- auto device = ec->device; // raw udev_device* for deeper inspection
-
- auto vendor = UdevEventPublisher::getValue(device, "ID_VENDOR");
+sc->devtype = "usb_device";
+
+// Retrieve a property from an event
+void myCallback(const UdevEventContextRef& ec) {
+ std::string vendor = UdevEventPublisher::getValue(
+ ec->device, "ID_VENDOR");
+ std::string model = UdevEventPublisher::getAttr(
+ ec->device, "idProduct");
}
```
\ No newline at end of file
diff --git a/osquery/events/linux/bpf/.bpferrorstate.md b/osquery/events/linux/bpf/.bpferrorstate.md
index 219a15712c6..1014efe9167 100644
--- a/osquery/events/linux/bpf/.bpferrorstate.md
+++ b/osquery/events/linux/bpf/.bpferrorstate.md
@@ -1,38 +1,35 @@
-Defines the `BPFErrorState` structure and related utilities for tracking and reporting errors encountered during BPF-based event collection in the osquery BPF publisher.
+Defines the `BPFErrorState` structure and utility functions for tracking, reporting, and clearing BPF-related error counters within the osquery BPF event publisher.
## Key Components
### `BPFErrorState` (struct)
-A container aggregating all BPF publisher error counters:
+A container aggregating all error counters produced during BPF event publishing:
| Field | Type | Description |
-|---|---|---|
-| `perf_error_counters` | `IPerfEventReader::ErrorCounters` | Errors from `perf_output` ring buffer reads |
-| `probe_error_counter` | `std::size_t` | Failures from BPF probes (e.g. string/buffer capture failures) |
+|-------|------|-------------|
+| `perf_error_counters` | `IPerfEventReader::ErrorCounters` | Errors from `perf_output` event reading |
+| `probe_error_counter` | `std::size_t` | Failures within loaded BPF probes (e.g., string or buffer capture failures) |
| `errored_tracer_list` | `std::unordered_set` | IDs of tracers that produced unprocessable events |
-### `updateBpfErrorState()`
-Merges incoming `perf_output` error counters into an existing `BPFErrorState` instance.
+### Functions
-### `reportAndClearBpfErrorState()`
-Logs the current error state (typically to the osquery logger) and resets all counters and sets to their zero/empty defaults.
+- **`updateBpfErrorState`** β Merges incoming `perf_output` error counters into an existing `BPFErrorState` instance.
+- **`reportAndClearBpfErrorState`** β Logs the current error state and resets all counters/sets to their zero/empty state.
## Usage Example
-```c
-BPFErrorState error_state{};
+```cpp
+#include "bpferrorstate.h"
-// After each perf reader poll cycle, merge new counters in
-IPerfEventReader::ErrorCounters new_counters = reader->getErrorCounters();
-updateBpfErrorState(error_state, new_counters);
+osquery::BPFErrorState error_state{};
-// Periodically flush errors to logs and reset state
-reportAndClearBpfErrorState(error_state);
-```
+// Update with new perf counters after each read cycle
+tob::ebpfpub::IPerfEventReader::ErrorCounters counters = reader->errorCounters();
+osquery::updateBpfErrorState(error_state, counters);
-## Notes
+// Periodically report and reset accumulated errors
+osquery::reportAndClearBpfErrorState(error_state);
+```
-- `probe_error_counter` covers soft failures such as truncated strings in `open` syscall captures or malformed `sockaddr_in` buffers β not fatal crashes.
-- `errored_tracer_list` deduplicates affected tracer IDs, making it useful for identifying persistently failing probes.
-- Both functions operate on `BPFErrorState` by reference, making them safe to use with a long-lived state object across polling intervals.
\ No newline at end of file
+> **Note:** `errored_tracer_list` captures tracers affected by lost events or probe-level failures. A non-empty set after a cycle indicates events may have been silently dropped and warrants investigation.
\ No newline at end of file
diff --git a/osquery/events/linux/bpf/.bpfeventpublisher.md b/osquery/events/linux/bpf/.bpfeventpublisher.md
index 1e344a84b2d..2c0cca1e380 100644
--- a/osquery/events/linux/bpf/.bpfeventpublisher.md
+++ b/osquery/events/linux/bpf/.bpfeventpublisher.md
@@ -1,54 +1,56 @@
-Header defining the `BPFEventPublisher` class for osquery's Linux BPF-based event publishing system, which captures and processes kernel syscall events via eBPF tracing.
+BPF-based event publisher for osquery on Linux that captures and processes kernel-level system call events using eBPF tracing infrastructure.
## Key Components
### Structs
-| Name | Base | Description |
-|------|------|-------------|
-| `BPFEventSC` | `SubscriptionContext` | Subscription context for BPF event subscriptions (opaque to subscribers) |
-| `BPFEventEC` | `EventContext` | Event context carrying a list of system state events (`ISystemStateTracker::EventList`) |
+| Name | Description |
+|------|-------------|
+| `BPFEventSC` | Subscription context for BPF events (opaque to subscribers) |
+| `BPFEventEC` | Event context carrying a list of tracked system state events |
### Class: `BPFEventPublisher`
-Extends `EventPublisher`. Manages the eBPF perf event reader lifecycle and dispatches processed syscall events to subscribers.
+Extends `EventPublisher` and manages the full lifecycle of eBPF-based syscall monitoring.
-**Lifecycle methods:**
+**Lifecycle Methods**
| Method | Description |
|--------|-------------|
-| `setUp()` | Initializes eBPF tracers and perf event reader |
+| `setUp()` | Initializes eBPF tracers and perf event readers |
| `configure()` | Applies runtime configuration |
-| `run()` | Poll loop consuming BPF perf events |
+| `run()` | Main loop β reads perf events and dispatches to subscribers |
| `tearDown()` | Cleans up eBPF resources |
-**Static helper β `getEventMapValue`**
+**Static Syscall Processors**
-Extracts a typed value from a `IFunctionTracer::Event::FieldMap` by key using `std::variant`. Returns `false` if the key is missing or the type doesn't match.
-
-**Static syscall processors**
-
-One handler per traced syscall, each updating an `ISystemStateTracker` with the parsed event:
+Each `process*Event` method handles a specific syscall traced via eBPF, updating the `ISystemStateTracker` accordingly:
- **Process lifecycle:** `processForkEvent`, `processVforkEvent`, `processCloneEvent`, `processExecveEvent`, `processExecveatEvent`
- **File descriptors:** `processCloseEvent`, `processDupEvent`, `processDup2Event`, `processDup3Event`, `processFcntlEvent`
-- **File system:** `processCreatEvent`, `processMknodatEvent`, `processOpenEvent`, `processOpenatEvent`, `processOpenat2Event`, `processChdirEvent`, `processFchdirEvent`, `processNameToHandleAtEvent`, `processOpenByHandleAtEvent`
+- **File system:** `processOpenEvent`, `processOpenatEvent`, `processOpenat2Event`, `processCreatEvent`, `processMknodatEvent`, `processChdirEvent`, `processFchdirEvent`, `processNameToHandleAtEvent`, `processOpenByHandleAtEvent`
- **Networking:** `processSocketEvent`, `processConnectEvent`, `processAcceptEvent`, `processAccept4Event`, `processBindEvent`, `processListenEvent`
+**Helper**
+
+`getEventMapValue` β typed extraction of a field value from an eBPF event's field map.
+
## Usage Example
```cpp
-// Retrieve a typed field from a BPF event map
-uint64_t fd = 0;
-bool ok = BPFEventPublisher::getEventMapValue(
- fd, event.field_map, "fd");
-
-if (ok) {
- // Use fd value
-}
-
-// Dispatch a clone syscall event to the state tracker
-bool handled = BPFEventPublisher::processCloneEvent(
- stateTracker, bpfEvent);
+// Extracting a field from a BPF event's field map
+uint64_t pid = 0;
+bool ok = BPFEventPublisher::getEventMapValue(
+ pid,
+ event.field_map,
+ "pid"
+);
+
+// Handling a fork syscall event against the state tracker
+bool handled = BPFEventPublisher::processForkEvent(stateTracker, bpfEvent);
+
+// Subscribing to BPF events
+auto sub_ctx = std::make_shared();
+EventFactory::addSubscription("BPFEventPublisher", sub_ctx, callback);
```
\ No newline at end of file
diff --git a/osquery/events/linux/bpf/.filesystem.md b/osquery/events/linux/bpf/.filesystem.md
index b295a6a391e..45083a5796a 100644
--- a/osquery/events/linux/bpf/.filesystem.md
+++ b/osquery/events/linux/bpf/.filesystem.md
@@ -1,48 +1,47 @@
-Concrete implementation of the `IFilesystem` interface for Linux BPF event processing, providing real filesystem operations backed by system calls.
+Concrete implementation of the `IFilesystem` interface for Linux BPF event processing, providing real filesystem operations backed by native system calls.
## Key Components
**`Filesystem`** β Final class implementing `IFilesystem` with the following methods:
| Method | Description |
-|---|---|
-| `open()` | Opens a file at the given path with specified flags, returning a unique fd |
-| `openAt()` | Opens a file relative to a directory fd (`dirfd`) |
-| `readLinkAt()` | Reads a symbolic link target relative to a directory fd |
-| `read()` | Reads up to `max_size` bytes from an open fd into a buffer |
+|--------|-------------|
+| `open()` | Opens a file at the given path with specified flags, returning a unique FD |
+| `openAt()` | Opens a file relative to a directory FD (`dirfd`) |
+| `readLinkAt()` | Resolves a symbolic link relative to a directory FD |
+| `read()` | Reads up to `max_size` bytes from an open FD into a buffer |
| `enumFiles()` | Enumerates files in a directory, invoking a callback per entry |
-| `fileExists()` | Checks whether a named file exists within a directory fd |
+| `fileExists()` | Checks whether a named file exists within a directory FD |
-> Construction is private (`Filesystem() = default`), enforcing instantiation exclusively through the `IFilesystem` factory (friend class pattern).
+**Construction** is private β instances are created exclusively through `IFilesystem` (factory pattern via `friend class IFilesystem`).
## Usage Example
```cpp
#include
-// Instantiate via the IFilesystem factory (not directly)
+// Obtain instance via the IFilesystem factory
auto fs = IFilesystem::create();
// Open a file
tob::utils::UniqueFd fd;
-if (fs->open(fd, "/proc/self/maps", O_RDONLY)) {
+if (fs->open(fd, "/proc/self/status", O_RDONLY)) {
std::vector buffer;
fs->read(buffer, fd.get(), 4096);
}
-// Check file existence relative to a directory fd
+// Check existence relative to a directory fd
bool exists = false;
-fs->fileExists(exists, AT_FDCWD, "config.json");
+fs->fileExists(exists, dirfd, "somefile.txt");
// Enumerate directory entries
-fs->enumFiles(AT_FDCWD, [](const std::string& name) {
- // process each entry
+fs->enumFiles(dirfd, [](const std::string& name, bool is_dir) {
+ // handle each entry
});
```
## Notes
-- Scoped to the `osquery` namespace
-- Designed for Linux only (BPF event subsystem)
-- All methods return `bool` indicating success/failure; output is via reference parameters
\ No newline at end of file
+- Instantiation is restricted to `IFilesystem` via the private constructor and `friend` declaration, enforcing use of the factory pattern.
+- Designed exclusively for the Linux BPF events subsystem within osquery.
\ No newline at end of file
diff --git a/osquery/events/linux/bpf/.processcontextfactory.md b/osquery/events/linux/bpf/.processcontextfactory.md
index dad39b819ef..d84786ac31f 100644
--- a/osquery/events/linux/bpf/.processcontextfactory.md
+++ b/osquery/events/linux/bpf/.processcontextfactory.md
@@ -1,51 +1,44 @@
-Concrete implementation of `IProcessContextFactory` for capturing Linux process context data by reading `/proc` filesystem entries via BPF event handling.
+Concrete implementation of `IProcessContextFactory` for capturing Linux process context data via the `/proc` filesystem using BPF event infrastructure.
## Key Components
-### Class: `ProcessContextFactory`
-
-Final implementation of `IProcessContextFactory` with both instance and static utility methods.
+### `ProcessContextFactory` (class)
+Final implementation of `IProcessContextFactory` that reads process metadata from the Linux `/proc` filesystem.
**Instance Methods**
+- `captureSingleProcess(ProcessContext&, pid_t)` β Captures context for a single process by PID
+- `captureAllProcesses(ProcessContextMap&)` β Captures context for all currently running processes
-| Method | Description |
-|---|---|
-| `captureSingleProcess(ProcessContext&, pid_t)` | Captures context for a single process by PID |
-| `captureAllProcesses(ProcessContextMap&)` | Captures context for all running processes |
-
-**Static Utility Methods**
-
-| Method | Description |
-|---|---|
-| `captureSingleProcess(IFilesystem&, ProcessContext&, pid_t)` | Filesystem-injectable single process capture |
-| `captureAllProcesses(IFilesystem&, ProcessContextMap&)` | Filesystem-injectable bulk process capture |
-| `getArgvFromCmdlineFile(IFilesystem&, vector&, int fd)` | Parses argv from `/proc//cmdline` |
-| `getParentPidFromStatFile(IFilesystem&, pid_t&, int fd)` | Extracts parent PID from `/proc//stat` |
+**Static Helpers**
+- `captureSingleProcess(IFilesystem&, ProcessContext&, pid_t)` β Filesystem-injectable variant for single process capture
+- `captureAllProcesses(IFilesystem&, ProcessContextMap&)` β Filesystem-injectable variant for bulk capture
+- `getArgvFromCmdlineFile(IFilesystem&, std::vector&, int fd)` β Parses argv from a `/proc//cmdline` file descriptor
+- `getParentPidFromStatFile(IFilesystem&, pid_t&, int fd)` β Extracts parent PID from a `/proc//stat` file descriptor
-**Private Members**
-- `IFilesystem::Ref fs` β injected filesystem abstraction for testability
-- Private constructor (instantiated via `IProcessContextFactory` friend)
+**Private**
+- `fs` β `IFilesystem::Ref` dependency used for `/proc` reads
+- Constructor is private; instantiation is controlled via `IProcessContextFactory` (friend)
## Usage Example
-```c
-// Typically instantiated through IProcessContextFactory
-auto factory = IProcessContextFactory::create(fs_ref);
+```cpp
+// Instantiation is handled via IProcessContextFactory factory method
+auto factory = IProcessContextFactory::create(filesystem_ref);
-// Capture a single process by PID
-ProcessContext ctx;
+// Capture a single process
+osquery::ProcessContext ctx;
if (factory->captureSingleProcess(ctx, 1234)) {
- // ctx now contains argv, parent PID, etc.
+ // ctx now populated with PID 1234's argv, ppid, etc.
}
-// Capture all running processes
-ProcessContextMap all_procs;
-factory->captureAllProcesses(all_procs);
+// Capture all processes
+osquery::ProcessContextMap process_map;
+factory->captureAllProcesses(process_map);
-// Static form β useful in tests with mock filesystem
-ProcessContext ctx2;
-ProcessContextFactory::captureSingleProcess(mock_fs, ctx2, 1234);
+// Using static helpers directly (e.g., in tests)
+ProcessContextFactory::getArgvFromCmdlineFile(fs, argv, fd);
+ProcessContextFactory::getParentPidFromStatFile(fs, parent_pid, fd);
```
-> **Note:** The private constructor and `friend class IProcessContextFactory` pattern enforces creation through the factory interface, enabling dependency injection of `IFilesystem` for unit testing.
\ No newline at end of file
+> The static method overloads accept an `IFilesystem&` parameter, enabling dependency injection for unit testing without requiring a real `/proc` filesystem.
\ No newline at end of file
diff --git a/osquery/events/linux/bpf/.serializers.md b/osquery/events/linux/bpf/.serializers.md
index e55d7396631..ed0df53416b 100644
--- a/osquery/events/linux/bpf/.serializers.md
+++ b/osquery/events/linux/bpf/.serializers.md
@@ -1,28 +1,20 @@
-Declares the `ParameterListMap` type and the `kParameterListMap` lookup table used to map eBPF function tracer names to their corresponding parameter lists.
+Defines the `ParameterListMap` type alias and declares the `kParameterListMap` constant used to map syscall/function names to their eBPF parameter list definitions for osquery's eBPF-based event tracing.
## Key Components
-| Symbol | Type | Description |
-|---|---|---|
-| `ParameterListMap` | Type alias | `unordered_map` keyed by `std::string`, mapping to `IFunctionTracer::ParameterList` |
-| `kParameterListMap` | `extern const` | Global registry of eBPF-traced function names to their parameter definitions |
+- **`ParameterListMap`** β Type alias for `std::unordered_map`, mapping function/syscall name strings to their corresponding eBPF parameter lists.
+- **`kParameterListMap`** β Externally declared constant map instance containing the pre-defined parameter list entries used during eBPF function tracing serialization.
## Usage Example
```cpp
#include "serializers.h"
-// Look up parameters for a known syscall tracer
-auto it = osquery::kParameterListMap.find("open");
+// Look up parameter list for a specific syscall
+auto it = osquery::kParameterListMap.find("execve");
if (it != osquery::kParameterListMap.end()) {
- const auto& params = it->second;
- // iterate or pass params to a function tracer
+ const auto& paramList = it->second;
+ // Use paramList with IFunctionTracer to configure eBPF probes
}
-```
-
-## Notes
-
-- Depends on `ebpfpub/ifunctiontracer.h` from the `tob::ebpfpub` namespace.
-- `kParameterListMap` is defined externally (in the corresponding `.cpp`); this header only declares it.
-- Intended for use within osquery's eBPF event tracing subsystem to drive syscall parameter serialization.
\ No newline at end of file
+```
\ No newline at end of file
diff --git a/osquery/events/linux/bpf/.setrlimit.md b/osquery/events/linux/bpf/.setrlimit.md
index 7af86cfb756..bb7f1bbbc0f 100644
--- a/osquery/events/linux/bpf/.setrlimit.md
+++ b/osquery/events/linux/bpf/.setrlimit.md
@@ -3,7 +3,7 @@ Declares a utility function for configuring BPF (Berkeley Packet Filter) memory
## Key Components
-- **`configureBPFMemoryLimits()`** β Sets system resource limits (`rlimit`) required for BPF operations. Returns a `Status` object indicating success or failure.
+- **`configureBPFMemoryLimits()`** β Sets system resource limits (`rlimit`) required for BPF operations. Returns an osquery `Status` object indicating success or failure.
## Usage Example
@@ -13,15 +13,12 @@ Declares a utility function for configuring BPF (Berkeley Packet Filter) memory
void initBPF() {
osquery::Status status = osquery::configureBPFMemoryLimits();
if (!status.ok()) {
- // Handle failure: status.getMessage() provides details
- return;
+ // Handle failure: status.getMessage() provides error details
}
- // Proceed with BPF initialization
}
```
## Notes
-- Part of the `osquery` namespace.
-- Relies on `osquery::Status` from `osquery/utils/status/status.h` for error propagation.
-- Typically called during BPF subsystem initialization to ensure adequate locked memory (`RLIMIT_MEMLOCK`) is available for eBPF map and program loading.
\ No newline at end of file
+- Returns `Status::success()` on success or a descriptive error `Status` on failure.
+- Typically called during BPF subsystem initialization to ensure sufficient locked memory (`RLIMIT_MEMLOCK`) is available for eBPF map and program loading.
\ No newline at end of file
diff --git a/osquery/events/linux/bpf/.systemstatetracker.md b/osquery/events/linux/bpf/.systemstatetracker.md
index 5c345dc8594..ee63c0f6cc2 100644
--- a/osquery/events/linux/bpf/.systemstatetracker.md
+++ b/osquery/events/linux/bpf/.systemstatetracker.md
@@ -1,52 +1,54 @@
-Concrete implementation of `ISystemStateTracker` that tracks Linux process and system state via BPF event hooks, maintaining per-process context maps and generating an event list from observed kernel activity.
+Concrete implementation of `ISystemStateTracker` that tracks Linux process and file descriptor state using BPF event data within the osquery framework.
## Key Components
-### Factory Methods
-- `create()` β Instantiates tracker with a default `IProcessContextFactory`
-- `create(IProcessContextFactory::Ref)` β Instantiates tracker with an injected factory (for testing)
+### Class: `SystemStateTracker`
+
+**Factory Methods**
+- `create()` β instantiates with a default `IProcessContextFactory`
+- `create(IProcessContextFactory::Ref)` β instantiates with a custom factory (useful for testing)
+
+**Instance Methods (ISystemStateTracker overrides)**
-### Instance Methods (virtual overrides)
| Method | Description |
|---|---|
-| `restart()` | Reinitializes tracker state |
-| `createProcess()` | Records a fork/clone event |
-| `executeBinary()` | Records an exec event with argv |
-| `setWorkingDirectory()` | Updates CWD by `dirfd` or path string |
-| `openFile()` / `closeHandle()` / `duplicateHandle()` | Tracks file descriptor lifecycle |
-| `createSocket()` / `bind()` / `listen()` / `connect()` / `accept()` | Tracks socket state transitions |
-| `nameToHandleAt()` / `openByHandleAt()` | Tracks opaque file handle resolution |
-| `eventList()` | Returns accumulated BPF events |
-
-### Internal Static Helpers
-- `getProcessContext()` β Looks up or creates a `ProcessContext` for a given PID
-- `expireProcessContexts()` β Prunes stale process entries
-- `parseUnixSockaddr()` / `parseInetSockaddr()` / `parseInet6Sockaddr()` / `parseNetlinkSockaddr()` β Deserializes raw sockaddr bytes into address/port strings
-- `parseSocketAddress()` β Dispatches to the appropriate sockaddr parser
-- `saveFileHandle()` / `expireFileHandleEntries()` β Manages the file handle index/map
-
-### Key Data Structures
-- `Context` β Holds the `ProcessContextMap`, accumulated `EventList`, and file handle index/map
-- `FileHandleStruct` β Associates a handle with its originating `dfd`, name, and flags
-- `PrivateData` β Opaque pImpl struct holding internal state
+| `createProcess` | Records a new child process fork event |
+| `executeBinary` | Tracks `execve`-style binary execution with argv |
+| `setWorkingDirectory` | Updates a process's `cwd` by fd or path |
+| `openFile` / `closeHandle` / `duplicateHandle` | Maintains per-process file descriptor table |
+| `createSocket` / `bind` / `listen` / `connect` / `accept` | Tracks socket lifecycle and addressing |
+| `nameToHandleAt` / `openByHandleAt` | Handles file-handle-based open operations |
+| `eventList` | Returns accumulated BPF events for consumption |
+| `restart` | Resets internal state |
+
+**Internal Structures**
+
+- `Context` β holds the `ProcessContextMap`, `EventList`, and file handle index/map
+- `FileHandleStruct` β stores `dfd`, `name`, and `flags` for a pending file handle
+- `PrivateData` β pimpl-pattern struct hiding implementation details
+
+**Static Helpers**
+- `parseUnixSockaddr` / `parseInetSockaddr` / `parseInet6Sockaddr` / `parseNetlinkSockaddr` β parse raw sockaddr bytes into address/port strings
+- `parseSocketAddress` β dispatches to the correct parser based on socket domain
+- `expireProcessContexts` / `expireFileHandleEntries` β prune stale entries to bound memory growth
## Usage Example
```cpp
-// Default construction
+// Create tracker with default factory
auto tracker = osquery::SystemStateTracker::create();
-// Process a fork event
+// Handle a fork BPF event
tracker->createProcess(event_header, parent_pid, child_pid);
-// Track a binary execution
-tracker->executeBinary(event_header, pid, AT_FDCWD, 0, "/usr/bin/ls", argv);
+// Handle an execve BPF event
+tracker->executeBinary(event_header, pid, AT_FDCWD, 0,
+ "/usr/bin/curl", argv);
-// Retrieve accumulated events
-auto events = tracker->eventList();
+// Handle socket connect
+tracker->connect(event_header, pid, sockfd, raw_sockaddr_bytes);
-// Inject a custom factory (e.g., in unit tests)
-auto mock_factory = std::make_shared();
-auto tracker = osquery::SystemStateTracker::create(mock_factory);
+// Drain events for processing
+auto events = tracker->eventList();
```
\ No newline at end of file
diff --git a/osquery/events/tests/.mockedosquerydatabase.md b/osquery/events/tests/.mockedosquerydatabase.md
index adf5afcc7e9..3d8d721bd3f 100644
--- a/osquery/events/tests/.mockedosquerydatabase.md
+++ b/osquery/events/tests/.mockedosquerydatabase.md
@@ -1,41 +1,48 @@
-In-memory mock implementation of `IDatabaseInterface` for use in osquery unit tests, providing a simple `std::map`-backed database without requiring a real storage backend.
+A test utility header defining an in-memory mock implementation of the osquery database interface, used to isolate unit tests from real database I/O.
## Key Components
-- **`MockedOsqueryDatabase`** β Final class implementing `IDatabaseInterface` with an in-memory `std::map key_map` as the backing store.
-- **`generateEvents()`** β Helper to simulate event generation for a given publisher and event name during tests.
-- **`getDatabaseValue()`** β Overloaded for `std::string` and `int` return types; reads from `key_map`.
-- **`setDatabaseValue()`** β Overloaded for `std::string` and `int` values; writes to `key_map`.
-- **`setDatabaseBatch()`** β Bulk insert of string key-value pairs into the mock store.
-- **`deleteDatabaseValue()`** / **`deleteDatabaseRange()`** β Remove single or range-bounded entries from `key_map`.
-- **`scanDatabaseKeys()`** β Overloaded to list keys within a domain, with optional prefix filtering and a result size limit.
+**`MockedOsqueryDatabase`** β A `final` class implementing `IDatabaseInterface` backed by an in-memory `std::map`.
+
+| Member | Description |
+|---|---|
+| `key_map` | Mutable in-memory store mapping keys to string values |
+| `generateEvents()` | Injects synthetic events for a given publisher/name pair |
+| `getDatabaseValue()` | Reads a `string` or `int` value by domain + key |
+| `setDatabaseValue()` | Writes a `string` or `int` value by domain + key |
+| `setDatabaseBatch()` | Writes multiple string values in one call |
+| `deleteDatabaseValue()` | Removes a single key from a domain |
+| `deleteDatabaseRange()` | Removes all keys between `low` and `high` in a domain |
+| `scanDatabaseKeys()` | Lists keys in a domain, optionally filtered by prefix and capped by `max` |
## Usage Example
```cpp
#include "mockedosquerydatabase.h"
-using namespace osquery;
+TEST(MyFeatureTest, StoresAndRetrievesValue) {
+ osquery::MockedOsqueryDatabase db;
-// Instantiate mock database for a unit test
-MockedOsqueryDatabase db;
+ // Write a value
+ db.setDatabaseValue("config", "version", std::string("1.0"));
-// Write a value
-db.setDatabaseValue("config", "refresh_interval", std::string("60"));
+ // Read it back
+ std::string value;
+ auto status = db.getDatabaseValue("config", "version", value);
-// Read it back
-std::string value;
-Status s = db.getDatabaseValue("config", "refresh_interval", value);
-assert(s.ok());
-assert(value == "60");
+ EXPECT_TRUE(status.ok());
+ EXPECT_EQ(value, "1.0");
+}
-// Scan keys in a domain
-std::vector keys;
-db.scanDatabaseKeys("config", keys, 100);
+TEST(MyFeatureTest, SimulatesEventPublishing) {
+ osquery::MockedOsqueryDatabase db;
+ db.generateEvents("file_events", "file_created");
-// Simulate event generation
-db.generateEvents("file_events", "file_created");
+ std::vector keys;
+ db.scanDatabaseKeys("events", keys, /* max */ 100);
+ EXPECT_FALSE(keys.empty());
+}
```
-> **Note:** `key_map` is `mutable` to allow `const`-qualified read/write methods to modify the in-memory store β a deliberate design choice for test convenience. Not intended for production use.
\ No newline at end of file
+> **Note:** All state lives in `key_map` and is discarded when the object goes out of scope β no cleanup or teardown required between tests.
\ No newline at end of file
diff --git a/osquery/events/tests/linux/bpf/.mockedfilesystem.md b/osquery/events/tests/linux/bpf/.mockedfilesystem.md
index 8f8daa9374c..aa8cc42e698 100644
--- a/osquery/events/tests/linux/bpf/.mockedfilesystem.md
+++ b/osquery/events/tests/linux/bpf/.mockedfilesystem.md
@@ -1,37 +1,40 @@
-A test double implementation of the `IFilesystem` interface that provides a mockable filesystem abstraction for unit testing BPF-related Linux event components without requiring real filesystem access.
+Declares `MockedFilesystem`, a test double implementing the `IFilesystem` interface for use in unit tests that require controlled, in-memory filesystem behavior without real I/O operations.
## Key Components
-### `MockedFilesystem` class
-
-Concrete final class inheriting from `IFilesystem`, overriding all virtual methods:
+**`MockedFilesystem`** β Final class inheriting from `IFilesystem`, overriding all virtual filesystem methods:
| Method | Description |
|---|---|
-| `open()` | Mocked file open by path with flags |
-| `openAt()` | Mocked file open relative to a directory fd |
-| `readLinkAt()` | Mocked symlink resolution relative to a directory fd |
-| `read()` | Mocked buffered file read up to a max size |
-| `enumFiles()` | Mocked directory file enumeration via callback |
-| `fileExists()` | Mocked existence check relative to a directory fd |
+| `open()` | Opens a file descriptor by path and flags |
+| `openAt()` | Opens a file descriptor relative to a directory fd |
+| `readLinkAt()` | Reads a symbolic link relative to a directory fd |
+| `read()` | Reads file contents into a buffer up to `max_size` |
+| `enumFiles()` | Enumerates files in a directory via callback |
+| `fileExists()` | Checks for file existence relative to a directory fd |
## Usage Example
```cpp
#include "mockedfilesystem.h"
-// Inject MockedFilesystem into a component under test
-osquery::MockedFilesystem mockFs;
+using namespace osquery;
+
+// Instantiate the mock in a test fixture
+MockedFilesystem fs;
-// Use with a BPF event processor that depends on IFilesystem
+// Use with a BPF event processor that accepts IFilesystem&
tob::utils::UniqueFd fd;
-bool success = mockFs.open(fd, "/proc/self/maps", O_RDONLY);
+bool success = fs.open(fd, "/proc/self/status", O_RDONLY);
+
+// Read contents into a buffer
+std::vector