diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 4fe9e2e0..00000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.claude/docs/sdk-docstring-conventions.md b/.claude/docs/sdk-docstring-conventions.md new file mode 100644 index 00000000..c9c41682 --- /dev/null +++ b/.claude/docs/sdk-docstring-conventions.md @@ -0,0 +1,105 @@ +# SDK Docstring Conventions + +Rules for docstrings in `limacharlie/sdk/`. Use this as a checklist during code review. + +## Format + +Google style. Every public method and class must have a docstring. + +## Required Sections + +| Section | When required | +|---------|--------------| +| Summary line | Always | +| `Args:` | Method takes parameters (excluding `self`) | +| `Returns:` | Method returns a value (not `None`) | +| `Yields:` | Method is a generator (uses `yield`) — use *instead of* `Returns:` | +| `Raises:` | Method raises an exception that callers should handle (auth errors, validation, not-found, etc.) | + +## Style Rules + +1. **Summary line**: imperative mood, one sentence, no trailing period when single line. +2. **Args**: one line per param — `name: Description.` (sentence case, ends with period). +3. **Returns / Yields**: `type: Description.` Keep it brief; mention key fields for dicts. +4. **Raises**: `ExceptionType: When it is raised.` +5. **Blank line** between summary and first section, and between sections. +6. **Type info in signatures, not docstrings** — the codebase uses type annotations; don't duplicate types in `Args:` descriptions. +7. **No `Returns:` for trivial wrappers** that clearly return "API response dict" — a one-liner docstring like `"""List all X."""` is fine if the return type annotation is `dict[str, Any]` and there is nothing surprising in the response shape. + +## Canonical Examples + +### Standard CRUD method + +```python +def create(self, name: str, description: str = "") -> dict[str, Any]: + """Create a new resource. + + Args: + name: Human-readable name. + description: Optional long description. + + Returns: + dict: API response containing the created resource. + """ +``` + +### Method that returns None + +```python +def delete(self, name: str) -> None: + """Delete a resource by name. + + Args: + name: Resource name. + """ +``` + +### Generator + +```python +def get_events(self, start: int, end: int) -> Generator[dict[str, Any], None, None]: + """Get historical events for this sensor. + + Args: + start: Start time (unix seconds). + end: End time (unix seconds). + + Yields: + dict: Event records with ``routing`` and ``event`` keys. + """ +``` + +### Method that raises + +```python +def download_binary(kind: str, platform: str, arch: str) -> bytes: + """Download a sensor installer or adapter binary. + + Args: + kind: ``'sensor'`` or ``'adapter'``. + platform: Platform name (e.g. ``'linux'``, ``'windows'``). + arch: Architecture (e.g. ``'64'``, ``'arm64'``). + + Returns: + bytes: Raw binary content. + + Raises: + ValueError: If the (platform, arch) combination is not valid. + RuntimeError: If the download fails. + """ +``` + +### Simple one-liner (acceptable for trivial getters) + +```python +def get_info(self) -> dict[str, Any]: + """Get organization details.""" +``` + +## Anti-patterns + +- Duplicating type annotations inside `Args:` descriptions (e.g., `name (str): ...`). +- Writing `Returns: dict` without saying what's in it when the shape is non-obvious. +- Using `Returns:` on a generator — use `Yields:` instead. +- Omitting `Args:` when the method has parameters beyond `self`. +- Adding docstrings to private methods (`_foo`) — not required. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..069a55bb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: + push: + branches: + - master + - cli-v2 + pull_request: + branches: + - master + - cli-v2 + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + test: + name: Unit tests (Python ${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + fetch-depth: 0 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: "${{ matrix.python-version }}" + allow-prereleases: true + - name: Install dependencies + run: | + pip install --upgrade pip + pip install ".[dev]" + # Python 3.9 needs tomli for pyproject.toml parsing in tests + if python -c "import sys; sys.exit(0 if sys.version_info < (3, 11) else 1)"; then + pip install "tomli>=1.0" + fi + - name: Run unit tests and microbenchmarks (correctness only) + run: pytest tests/unit/ tests/microbenchmarks/ --benchmark-disable -v --reruns 2 --reruns-delay 5 diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml new file mode 100644 index 00000000..c99f3bc7 --- /dev/null +++ b/.github/workflows/publish-to-pypi.yml @@ -0,0 +1,81 @@ +name: Publish to PyPI + +on: + push: + tags: + - "[0-9]+.[0-9]+.[0-9]+" + +permissions: + contents: read + +jobs: + test: + name: Unit tests (Python ${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + fetch-depth: 0 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: "${{ matrix.python-version }}" + allow-prereleases: true + - name: Install dependencies + run: | + pip install --upgrade pip + pip install ".[dev]" + # Python 3.9 needs tomli for pyproject.toml parsing in tests + if python -c "import sys; sys.exit(0 if sys.version_info < (3, 11) else 1)"; then + pip install "tomli>=1.0" + fi + - name: Run unit tests and microbenchmarks (correctness only) + run: pytest tests/unit/ tests/microbenchmarks/ --benchmark-disable -v --reruns 2 --reruns-delay 5 + + build: + name: Build distribution packages + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.11" + - name: Install build + run: pip install build + - name: Build sdist and wheel + run: python -m build + - name: Upload distributions + uses: actions/upload-artifact@v7 + with: + name: python-package-distributions + path: dist/ + + publish: + name: Publish to PyPI + needs: build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/limacharlie + permissions: + id-token: write + attestations: write + contents: read + steps: + - name: Download distributions + uses: actions/download-artifact@v8 + with: + name: python-package-distributions + path: dist/ + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.gitignore b/.gitignore index 7bbc71c0..60161392 100644 --- a/.gitignore +++ b/.gitignore @@ -99,3 +99,6 @@ ENV/ # mypy .mypy_cache/ + +# setuptools-scm generated version file +limacharlie/_version.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 07fcb707..8f43d5e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,522 @@ # Changelog -## 4.11.2 - January 13th, 2026 +## 5.2.0 - March 20, 2026 + +### CLI + +- **Lazy command loading**: CLI startup is significantly faster. Commands are + now loaded on-demand via a static map instead of eagerly importing all 49 + modules. `limacharlie.output` import is deferred to the CLI callback. + Performance improvements across all operations (#261): + - `limacharlie --version`: 114ms -> 55ms (52% faster) + - `limacharlie --help`: 537ms -> 176ms (67% faster) + - `limacharlie sensor list --help`: 220ms -> 105ms (52% faster) + +- **`__version__` fix**: `limacharlie.__version__` now returns the correct + version instead of `0.0.0.dev0`. Version is imported directly from `_version` + (generated by setuptools-scm) instead of from `client.py` (#261). + +- **Help topic name matching**: Help topics now match CLI command names + (singular form). Both singular and plural forms resolve - e.g. + `limacharlie help output` and `limacharlie help outputs` both work (#263). + +### Configuration + +- **Consolidated config directory**: All CLI config files (credentials, JWT + cache, search checkpoints) are now unified under `~/.limacharlie.d/` on Unix + and `%APPDATA%/limacharlie/` on Windows. A new `paths.py` module is the + single source of truth for all path resolution (#257). + + Legacy `~/.limacharlie` configs are auto-detected with a warning. Users can + migrate at their own pace via `limacharlie config migrate` (supports + `--dry-run`, `--remove-old`, `--force`). Content verification before legacy + file removal prevents data loss. + +- **`config show-paths` command**: Displays all resolved paths, existence + flags, and active environment variable overrides (#257). + +- **`config migrate` command**: Copies files from legacy flat-file layout to + the new `~/.limacharlie.d/` directory structure (#257). + +- **New environment variables**: `LC_CONFIG_DIR` (override config directory), + `LC_LEGACY_CONFIG=1` (force legacy layout, no warnings), + `LC_NO_MIGRATION_WARNING=1` (suppress migration warning only) (#257). + +### Cases + +- **Summary on case create**: `case create` now accepts `--summary` to set a + summary at creation time. The `Cases.create_case()` SDK method also accepts + the new `summary` parameter (#262). + +### Documentation + +- **Shell completion setup**: Added setup instructions for bash, zsh, and fish + tab-completion to the README (#260). + +### CI + +- **Version consistency checks**: All distribution build steps now verify that + `importlib.metadata.version()` matches `limacharlie.__version__` and that the + version is not the fallback `0.0.0.dev0` (#261). + +- **PyPI stable sanity check**: New Cloud Build step installs the latest stable + release from PyPI and verifies package imports, CLI entry point, `--help`, + SDK core imports, key command groups, and completion generation (#261). + +## 5.1.0 - March 18, 2026 + +### Search + +- **Streaming output**: Search results are now streamed with constant memory + for JSONL, JSON, expand, and table output formats. Previously all results + were buffered in memory before rendering, which could cause OOM on large + result sets (100K+ events). Memory behavior by format: + - JSONL/JSON/expand: O(1) - one result at a time + - table (live search): O(sample) - buffers ~3 pages for column width + sampling, then streams remaining rows + - table (checkpoint): O(columns) - two-pass file scan computes exact column + widths without loading rows into memory + - CSV/YAML: O(N) - inherent to format, unchanged + + Validated with a 30-day production search: RSS stabilized at 138 MB while + the checkpoint file grew to 632 MB (484 result pages). + +- **orjson integration**: Added `orjson` as an optional JSON backend (~3-10x + faster than stdlib `json`). Used automatically when available for all JSON + serialization/deserialization. Falls back to stdlib `json` if orjson cannot + be installed on the platform. + +- **Search poll retry with exponential backoff**: Individual poll GET requests + that fail with transient errors (5xx, connection reset, timeout, SSL errors) + are now automatically retried with exponential backoff (1s, 2s, 4s... capped + at 30s, default 3 retries). Permanent errors (401, 403, 404, 422, 429) and + search-engine body errors (e.g. "context canceled") are NOT retried. + +- **Checkpoint/resume support**: New `--checkpoint`, `--resume`, and `--force` + flags for `search run` allow incremental persistence of search results to a + JSONL file. If the search is interrupted (Ctrl+C, network error, token + expiry), the checkpoint preserves all results fetched so far. Resume uses + server-side pagination tokens to skip directly to the next un-fetched page + (no re-fetching). The server re-runs the query from the cursor position + embedded in the token, so resume works even after long delays between + sessions. + +- **`search checkpoints` command**: Lists all local checkpoints with pages, + events, time range progress %, token, and timestamps. Automatically cleans + up stale metadata when data files are deleted. Shows human-readable file + size. Sorted by created timestamp descending (most recent first). + +- **`search checkpoint-show` command**: Displays results from a checkpoint data + file through the same output pipeline as a live search (table, JSON, expand, + raw, JSONL). Streams with constant memory for all formats except CSV/YAML. + +- **Large search warnings**: Two independent warnings for searches without + `--checkpoint`: + 1. Memory warning (>7 days, CSV/YAML only): suggests streaming formats or + `--checkpoint`. + 2. Resumability warning (>14 days, all formats): recommends `--checkpoint` + so interrupted searches can be resumed. + +- **`--expand` flag**: New flag for `search run`, `search saved-run`, and + `search checkpoint-show` that shows each event as a pretty-printed JSON block + with a header showing timestamp, stream, and event type. Useful for + investigating individual events in detail. + +- **`--raw` flag**: New flag that shows the raw SearchResult API objects without + unwrapping. Useful for debugging or accessing metadata like searchResultId, + nextToken, and stats. + +- **Checkpoint security hardening**: Checkpoint metadata directories + (`~/.limacharlie.d/search_checkpoints/`) are created with 0o700 (owner-only) + permissions. Data files use `O_EXCL|O_NOFOLLOW` for atomic creation with + symlink rejection. All files get 0o600 permissions. + +- **Billing cost notice**: Searches spanning more than 30 days now show a + notice that additional costs may apply (data older than 30 days is not + included in the base subscription). The notice includes the exact + `limacharlie search estimate` command to check costs before running. + +- **Validate/estimate exit codes**: `search validate` and `search estimate` + now exit with code 1 when the server returns an error (e.g. invalid query + syntax). Previously they always exited 0 regardless of the response. + +- **Validate/estimate table output**: Stats and estimatedPrice fields are now + flattened into individual columns (e.g. `stats.bytesScanned`, + `price.value`) instead of being shown as truncated `{N keys}` summaries. + Machine-readable formats (JSON, YAML) preserve the original nested + structure. + +- **Structured search errors**: Search failures now raise `SearchError` with + `query_id`, `region`, `oid`, and `query` attributes for easier troubleshooting. + Error messages include these fields in bracket-formatted context: + `"Search failed [query_id=q-123, region=9157798c50af372c, oid=..., query=...]"`. + Long queries are truncated to 120 characters in the message but the full query + is always available via the `query` attribute. + +- **Region extraction**: The search region identifier (hex hash from the search + URL) is automatically extracted and included in error messages. + +- **Default search token expiry**: Search queries (`search run`, `search saved-run`) + now automatically generate a 4-hour JWT token instead of the default ~1 hour. + This prevents mid-query JWT expiry on long-running searches. The default can be + overridden via the `--token-expiry` CLI flag or by setting + `search_token_expiry_hours` in `~/.limacharlie`. + +- **Human-readable table output**: Search results in table mode are now + unwrapped - event rows are flattened into a single table with timestamps, + stream type, routing metadata, and event data as columns. Stats are shown on + stderr. Machine-readable formats pass through the raw API response unchanged. + +### Authentication + +- **On-disk JWT caching**: JWTs are now cached to disk at + `~/.limacharlie_jwt_cache` so that repeated CLI invocations reuse the same + token instead of generating a new one each time. This reduces the number of + active JWTs, eliminates a ~100-200ms HTTP roundtrip per command, and lowers + load on `jwt.limacharlie.io`. Cached tokens are reused until they are within + 10 minutes of expiry, then a fresh one is fetched and cached automatically. + + The cache works for both API key and OAuth authentication paths. Search + commands (`search run`, `search saved-run`) also benefit: if the cached JWT + has enough remaining TTL for the requested expiry (default 4 hours), it is + reused instead of generating a new long-lived token. + + If the server rejects a cached JWT (401), it is automatically invalidated, a + fresh token is fetched, cached, and the request is retried. + + **Cache file security:** + - File permissions: 0o600 (owner-only read/write) + - Atomic writes via tempfile + `os.replace` (no partial reads) + - Symlink rejection on read and write paths (`O_NOFOLLOW` on Unix) + - Cross-platform (Linux, macOS, Windows) + + **Disabling the cache:** + + There are three ways to disable JWT caching: + + 1. Set the `LC_NO_JWT_CACHE` environment variable: + ```bash + LC_NO_JWT_CACHE=1 limacharlie sensors list + ``` + + 2. Set `no_jwt_cache: true` in `~/.limacharlie`: + ```yaml + oid: my-org-id + api_key: my-api-key + no_jwt_cache: true + ``` + + 3. Use ephemeral credentials mode (also disables config file): + ```bash + LC_EPHEMERAL_CREDS=1 LC_OID=... LC_API_KEY=... limacharlie sensors list + ``` + + **Debug logging:** + + Use `--debug` to see cache operations: + ``` + $ limacharlie --debug sensors list + 2026-03-14 12:00:00Z: JWT cache: checking /home/user/.limacharlie_jwt_cache + 2026-03-14 12:00:00Z: JWT cache: hit, reusing cached token (expires in 2847s, 47m) + ``` + +- **`auth get-token` command**: New command to generate JWT tokens with custom + expiry for long-running operations. Supports `--hours` for expiry duration and + `--format json` for metadata output (token, expiry timestamp, oid). + +- **`Client.get_jwt()` SDK method**: New method to generate JWT tokens with + custom expiry programmatically. + +### Cases + +- **Severity on case update**: `case update` now accepts `--severity` to set + or change the severity level of an existing case. + +### CLI + +- **`--no-warnings` flag**: New global flag that suppresses all advisory + warnings (billing cost notices, memory buffering hints, checkpoint + suggestions, token expiry warnings). Does not suppress errors or result + output. Also configurable via `no_warnings: true` in `~/.limacharlie` + for CI/CD pipelines. + +- **`-h` short flag for help**: The `-h` flag now works on all commands and + subcommands (previously only `--help` was recognized). Added + `context_settings={"help_option_names": ["-h", "--help"]}` to the root + Click group which propagates to all subcommands. + +- **`--debug` for all commands**: The `--debug`, `--debug-full`, and + `--debug-curl` flags now work on all CLI commands. Previously several + commands were not wiring `debug_fn` through to the SDK `Client`. + +- **Search subcommand help text**: Added missing Click docstrings for + `validate`, `estimate`, `saved-get`, `saved-create`, `saved-delete`, + `saved-run`, and `checkpoint-show` commands. + +- **Updated `--ai-help` for search**: Added output format documentation to + `search run` explain text covering streaming vs buffered behavior, + `--expand`, `--raw`, and memory guidance. + +### Packaging + +- **PyPI metadata**: Added project URLs (Documentation, Repository, Issues, + Changelog, REST API Docs) so links render correctly on the PyPI page. + Updated description to "Python SDK and CLI for the LimaCharlie endpoint + detection and response platform". + +- **Python 3.9-3.14 support**: Added PyPI classifiers for Python 3.9 through + 3.14. CI now runs distribution install checks on all supported versions + (3.9, 3.10, 3.11, 3.12, 3.13, 3.14) in parallel. + +- **PyPI classifiers**: Added classifiers for development status + (Production/Stable), audience (Developers, System Administrators), and topic + (Security, System Monitoring). + +### Dependencies + +- **orjson**: Added as a runtime dependency for ~3-10x faster JSON + serialization/deserialization. Uses split environment markers for Python + version compatibility: + - Python 3.9: orjson 3.10.x (last series with 3.9 support, capped `<3.11`) + - Python 3.10+: latest orjson (currently 3.11.x) + Falls back to stdlib `json` if orjson cannot be installed on the platform. + +### Configuration + +- **`get_config_value()` function**: New config helper for reading arbitrary + config keys with environment-aware lookup. + +- **Per-process config caching**: `load_config()` now caches its result for the + process lifetime, avoiding repeated YAML parsing when multiple subsystems + read the config file. + +- **Cross-platform `save_config()`**: Config file writes now use a shared + cross-platform `atomic_write` helper, fixing an existing bug on Windows where + the Unix-only `os.chown` call would fail. + +## 5.0.9 - March 13, 2026 + +- Add info severity level to cases CLI and SDK (#246). +- Add AI session lifecycle management and usage tracking (#245). + +## 5.0.8 - March 12, 2026 + +- Clarify `key` vs `json_key` in installation key help for AI guidance (#244). + +## 5.0.7 - March 11, 2026 + +- Update `ext-ticketing` references to `ext-cases` (#243). + +## 5.0.6 - March 11, 2026 + +- Follow pagination tokens in search SDK to return all result pages (#242). + +## 5.0.5 - March 10, 2026 + +- Rename ticket to case in SDK and CLI (#241). + +## 5.0.4 - March 10, 2026 + +- Fix `auth whoami` without OID - now falls back to "-" instead of erroring (#240). + +## 5.0.3 - March 10, 2026 + +- Add `--check-perm` and `--show-perms` flags to `auth whoami` (#239). +- Add `--data` option to `ai start-session` command (#238). +- Fix: don't send null data in metadata-only hive set requests (#236). +- Support full detection object in case create and detection add (#235). +- Fix `org list` to auto-paginate and return all results (#234). +- Fix help topic fallthrough, whoami output, and sync debug logging (#233). +- Fix enable/disable to preserve existing metadata (#232). +- Add enable/disable commands for Hive records (#231). +- Add `--sid` filter to case list for cross-detection sensor search (#230). +- Add case CLI commands for SOC case management (#224). +- Add AI session creation via ai_agent Hive definitions (#229). +- Fix incorrect LCQL syntax in search help, examples, and tests. +- Clean up CLI docstrings and standardize SDK documentation (#225). + +## 5.0.2 - February 27, 2026 + +- Add `--use` flag to `org create` (#223). +- Add `dr convert-rules` CLI command for mass rule conversion (#220). +- Switch from TestPyPI to PyPI (#221). + +## 5.0.1 - February 26, 2026 + +- Bump version to 5.0.1 for release (#218). +- Add `installation-key get` CLI command (#217). +- Fix incorrect location names in org create CLI help (#216). +- Update cloudbuild-pr image (#215). +- Add PyPI publishing via GitHub Actions (#214). +- Show web app URL after org create (#219). + +## 5.0.0 - February 25, 2026 + +Complete rewrite of the CLI and SDK. This is a major release with breaking +changes. + +### CLI Rewrite + +- **Click framework**: The CLI has been rewritten from scratch using Click, + replacing the legacy argparse-based implementation. All commands now follow a + consistent `limacharlie ` pattern across 50+ command groups. + +- **Modular command architecture**: Each command group lives in its own module + under `limacharlie/commands/`. Commands are auto-discovered and registered + at startup. + +- **Global option hoisting**: Options like `--output`, `--filter`, `--wide`, + and `--oid` can appear anywhere on the command line, not just before the + subcommand. + +- **Smart output formatting**: New unified output system supporting JSON, YAML, + CSV, table, and JSONL formats. TTY output defaults to tables with smart + column truncation; piped output defaults to JSON. Use `--wide` to disable + truncation, `--filter` for JMESPath expressions, and `--fields` for column + selection. + +- **Columnar tables for nested data**: Dict-of-dicts API responses are now + rendered as columnar tables instead of key/JSON pairs. + +- **Unwrapped API responses**: The SDK strips useless wrapper keys from API + responses (e.g. `{"sensors": {...}}` returns the inner dict directly). + +### Authentication + +- **OAuth login**: `limacharlie auth login --oauth` opens a browser for Google + or Microsoft authentication with MFA/2FA support. Use `--no-browser` for + headless environments. Tokens are automatically refreshed on expiry. + +- **Account signup**: `limacharlie auth signup` provides a full self-service + onboarding flow (OAuth, account creation, organization setup). + +- **Named environments**: The credential file (`~/.limacharlie`) now supports + multiple named environments for multi-org workflows. Switch with + `limacharlie auth use-env `. + +- **Early OID validation**: Missing organization ID is detected before any API + call with an actionable error instead of a confusing "unknown api key" + message. + +- **Credential resolution order**: Explicit parameters, then environment + variables (`LC_OID`, `LC_API_KEY`, `LC_UID`, `LC_CURRENT_ENV`), then named + environment from config, then default credentials. New `LC_CREDS_FILE` and + `LC_EPHEMERAL_CREDS` variables for CI/CD use. + +### New SDK + +- **New `Client` class** (`limacharlie/client.py`): Redesigned HTTP client with + built-in JWT generation/refresh, exponential backoff retry, rate limit + handling, and request debugging (`--debug`). + +- **30+ SDK modules** under `limacharlie/sdk/`: Clean, composable interfaces + covering the full LimaCharlie API surface, including: `organization`, + `sensor`, `dr_rules`, `fp_rules`, `hive`, `search`, `insight`, `spout`, + `firehose`, `artifacts`, `payloads`, `outputs`, `extensions`, `users`, + `groups`, `api_keys`, `billing`, `ai`, `investigations`, `jobs`, `yara`, + `configs`, `downloads`, `replay`, `integrity`, `exfil`, `logging_rules`, + `installation_keys`, `arl`, `usp`. + +- **Custom exception hierarchy**: All errors inherit from `LimaCharlieError` + with meaningful exit codes (0=success, 1=general, 2=auth, 3=not found, + 4=validation, 5=rate limit) and actionable suggestion messages. + +### AI-First Discoverability + +- **`--ai-help` flag**: Available on every command and command group. Generates + compact markdown with purpose, patterns, examples, and data structures, + designed for LLM consumption. Replaces the old `--explain` flag. + +- **`limacharlie discover`**: Lists all commands grouped by use-case profiles + (sensor management, detection engineering, historical data, live + investigation, threat response, fleet management, platform admin). + +- **`limacharlie help `**: Inline help topics for LCQL, D&R rules, hive + concepts, and more. + +### New Commands + +- `auth` - Login, logout, signup, whoami, environment management. +- `org` - Organization info, stats, URLs, config, errors, MITRE coverage, + schema inspection, creation/deletion. +- `sensor` - List (with `--online` and `--selector` filters), get, delete, + upgrade, export, dump, sweep, wait-online. +- `rule` / `fp` - D&R and false-positive rule CRUD, validation, testing, + replay, import/export. +- `hive` / `secret` / `lookup` / `playbook` / `sop` - Generic and shortcut + hive operations with validation. +- `task` - Sensor tasking including reliable task queues. +- `stream` - Real-time event, detection, and audit streaming (WebSocket and + legacy TCP/TLS firehose). +- `search` - LCQL queries with estimation, validation, streaming, interactive + REPL, and saved query management. +- `event` / `detection` / `audit` - Event inspection, detection browsing, audit + log listing. +- `ioc` - IOC search, batch search, enrichment, host queries. +- `tag` - Individual and bulk tag operations. +- `endpoint-policy` - Network isolation, boot integrity sealing, status. +- `investigation` - Investigation management with automatic expansion. +- `ai` - LLM-powered rule, detection, response, and query generation. +- `extension` - Extension subscription, configuration, schema inspection. +- `download` - Sensor installer and adapter binary downloads. +- `output` / `artifact` / `payload` - Output integrations, artifact management, + payload management. +- `user` / `group` / `api-key` - User, group, and API key management. +- `installation-key` / `ingestion-key` - Deployment key management. +- `external-adapter` / `cloud-adapter` / `cloud-sensor` - Adapter and cloud + sensor configuration. +- `billing` - Billing status and invoicing. +- `yara` - YARA rule scanning. +- `replay` - Rule replay operations. +- `integrity` / `exfil` / `logging` - Integrity monitoring, exfiltration + prevention, log collection rules. +- `sync` - Infrastructure-as-Code pull/push/diff. +- `job` / `spotcheck` / `arl` / `usp` / `note` / `schema` - Additional + management commands. + +### Sync Changes + +- The sync system now uses the `ext-infrastructure` extension exclusively. +- Legacy `--rules` and `--fps` flags are replaced with hive-based flags + (`--hive-dr-general`, `--hive-fp`, etc.). +- Version 3 configuration format with hive-based resource organization. + +### Testing + +- 60+ unit test files and 30+ integration test files covering all command + groups, SDK modules, config management, output formatting, and OAuth flows. +- Comprehensive HTTP contract tests validating SDK methods against the Go + backend API. + +### Packaging + +- Migrated from `setup.py` to `pyproject.toml`. +- Added type annotations and a `py.typed` marker. +- Minimum Python version: 3.9. +- New dependencies: `click>=8.0`, `jmespath`. +- Entry point changed to `limacharlie.cli:main`. + +### Breaking Changes + +- The legacy `Manager`, `Sensor`, and `Spout` classes have been replaced by the + new SDK modules. +- CLI entry point moved from `limacharlie.__main__:main` to + `limacharlie.cli:main`. +- `limacharlie login` is now `limacharlie auth login`. +- `--explain` renamed to `--ai-help`. +- `adapter` command split into `external-adapter` and `cloud-adapter`. +- `net-policy` renamed to `endpoint-policy`. +- `sensor online` removed; use `sensor list --online` instead. +- Sync flags `--rules`/`--fps` removed; use `--hive-dr-general`/`--hive-fp`. +- API responses are unwrapped by default (wrapper keys stripped). +- Configuration file format extended with named environments and OAuth token + storage. + +## 4.11.3 - January 15, 2026 + +- Internal packaging fix. + +## 4.11.2 - January 13, 2026 - Add support for `external_adapter` hive in the SDK and CLI. @@ -45,7 +561,7 @@ evt_sources: "DhcpAdminEvents:'*'" ``` -## 4.11.1 - January 12th, 2026 +## 4.11.1 - January 12, 2026 - Add support for `model` and `ai_agent` hives in the SDK and CLI. @@ -64,7 +580,7 @@ limacharlie configs push --hive-model --hive-ai-agent ``` -## 4.11.0 - December 18th, 2025 +## 4.11.0 - December 19, 2025 - Add SDK methods and CLI commands for the new Search API. @@ -192,7 +708,7 @@ ``` -## 4.9.13 - February 24th, 2025 +## 4.9.13 - February 24, 2025 - Fix Docker image build. @@ -206,7 +722,7 @@ * `refractionpoint/limacharlie:latest` -> Always points to the latest release. * `refractionpoint/limacharlie:4.9.13` -> Release version 4.9.13. -## 4.9.12 - February 21st, 2025 +## 4.9.12 - February 21, 2025 - Add `whoami` alias for `who` command. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 18d44639..00000000 --- a/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM python:3.12-slim -ADD . /python-limacharlie -WORKDIR /python-limacharlie -RUN python -m pip install "setuptools==75.8.0" -RUN python ./setup.py install - -ENTRYPOINT [ "limacharlie" ] diff --git a/NEW_CLI.md b/NEW_CLI.md new file mode 100644 index 00000000..e2bd8620 --- /dev/null +++ b/NEW_CLI.md @@ -0,0 +1,1291 @@ +# LimaCharlie Python SDK & CLI v2.0.0 - Design & Implementation Plan + +## Executive Summary + +This document describes the design for a complete rewrite of the LimaCharlie Python SDK and CLI (v2.0.0). The primary design goal is **AI/LLM-first discoverability**: every command, parameter, and concept should be self-documenting enough that an AI agent (like Claude Code) can operate the CLI effectively without prior LimaCharlie knowledge. + +The new CLI covers 100%+ of the current CLI features, plus new capabilities from the API gateway (AI generation, groups, investigations, SOPs, org notes, etc.). + +--- + +## Table of Contents + +1. [Design Principles](#1-design-principles) +2. [CLI Architecture](#2-cli-architecture) +3. [Authentication & Configuration](#3-authentication--configuration) +4. [SDK Core Classes](#4-sdk-core-classes) +5. [Command Groups & Commands](#5-command-groups--commands) +6. [Output & Formatting](#6-output--formatting) +7. [AI/LLM Discoverability Features](#7-aillm-discoverability-features) +8. [Testing Strategy](#8-testing-strategy) +9. [Migration & Packaging](#9-migration--packaging) +10. [Detailed Command Reference](#10-detailed-command-reference) +11. [Implementation Checklist](#11-implementation-checklist) + +--- + +## 1. Design Principles + +### 1.1 AI/LLM-First Discoverability +- [ ] Every command has a `--explain` flag that prints a detailed paragraph explaining what the command does, when to use it, and common patterns +- [ ] Every parameter has a rich `help=` string with type info, examples, and constraints +- [ ] `limacharlie help ` provides concept guides (e.g., `limacharlie help d&r-rules`, `limacharlie help hive`, `limacharlie help lcql`) +- [ ] `limacharlie discover` lists all commands grouped by use-case profile (matching MCP server profiles: sensor_management, detection_engineering, platform_admin, etc.) +- [ ] `limacharlie cheatsheet ` prints quick-reference examples +- [ ] Every error message includes a suggestion for what to do next +- [ ] JSON Schema output available for every command's parameters via `limacharlie schema ` + +### 1.2 Consistent Command Structure +- [ ] All commands follow `limacharlie ` pattern (e.g., `limacharlie sensor list`, `limacharlie rule create`) +- [ ] CRUD operations use consistent verbs: `list`, `get`, `create`, `update`, `delete` +- [ ] Bulk operations use consistent verbs: `export`, `import`, `sync` +- [ ] Destructive operations require `--confirm` or print a confirmation prompt +- [ ] All identifiers use consistent flag names: `--oid`, `--sid`, `--name`, `--key` + +### 1.3 Machine-Readable Output +- [ ] Default output is human-readable tables (for interactive use) +- [ ] `--output json` for JSON (default when stdout is piped/not a TTY) +- [ ] `--output yaml` for YAML +- [ ] `--output csv` for CSV +- [ ] `--output jsonl` for newline-delimited JSON (for streaming) +- [ ] `--quiet` / `-q` suppresses all output except errors +- [ ] Exit codes are meaningful: 0=success, 1=general error, 2=auth error, 3=not found, 4=validation error + +### 1.4 Composability +- [ ] All commands accept `--oid` to specify org (overrides env/config) +- [ ] All create/update commands support `--input-file` to read parameters from JSON/YAML file (rule create, hive set, output create, extension config set, etc.) +- [ ] All list commands support `--filter` for client-side jmespath filtering +- [ ] All list commands support `--limit` and `--offset` for pagination +- [ ] Stdin support for piping data between commands + +--- + +## 2. CLI Architecture + +### 2.1 Entry Point & Framework +- [ ] Use `click` library for CLI framework (replacing raw argparse) +- [ ] Single entry point: `limacharlie` command with click groups +- [ ] Plugin architecture: each command group is a separate module auto-discovered from `limacharlie/commands/` +- [ ] Global options: `--oid`, `--env`, `--output`, `--debug`, `--quiet`, `--profile` +- [ ] Version command: `limacharlie version` (replaces `limacharlie version`) + +### 2.2 Module Structure + +v2 replaces the existing code directly in the `limacharlie/` package (no backwards compatibility with v1 needed). Old v1 modules are removed. + +``` +limacharlie/ +├── __init__.py +├── __main__.py # Entry point: limacharlie CLI +├── cli.py # Main CLI entry point & click groups +├── config.py # Auth & configuration management +├── client.py # HTTP client with retry, auth, rate limiting +├── output.py # Output formatting (json/yaml/csv/table) +├── errors.py # Custom exception hierarchy +├── help_topics.py # Inline help topic content +├── discovery.py # Command discovery & explain system +├── sdk/ +│ ├── __init__.py +│ ├── organization.py # Organization management +│ ├── sensor.py # Sensor operations +│ ├── dr_rules.py # Detection & Response rules +│ ├── fp_rules.py # False positive rules +│ ├── hive.py # Hive key-value store +│ ├── outputs.py # Output integrations +│ ├── artifacts.py # Artifact/log management +│ ├── payloads.py # Payload management +│ ├── search.py # Search & LCQL queries +│ ├── insight.py # IOC search & event queries +│ ├── extensions.py # Extension management +│ ├── installation_keys.py # Installation key management +│ ├── ingestion_keys.py # Ingestion key management +│ ├── users.py # User & permission management +│ ├── groups.py # Organization group management +│ ├── api_keys.py # API key management +│ ├── billing.py # Billing & usage +│ ├── spout.py # Real-time streaming (WebSocket) +│ ├── firehose.py # Real-time streaming (TCP/TLS) +│ ├── replay.py # D&R rule replay/testing +│ ├── integrity.py # Integrity monitoring rules +│ ├── exfil.py # Exfil prevention rules +│ ├── logging_rules.py # Logging/log collection rules +│ ├── configs.py # Configuration sync (IaC) +│ ├── ai.py # AI-powered generation +│ ├── investigations.py # Investigation management +│ ├── usp.py # USP adapter validation +│ ├── jobs.py # Service job tracking +│ ├── yara.py # YARA scanning & rule management +│ └── arl.py # Authenticated Resource Locator resolution +├── commands/ +│ ├── __init__.py +│ ├── auth.py # login, logout, whoami, use-org +│ ├── sensor.py # sensor list, get, delete, upgrade, export, dump, sweep +│ ├── rule.py # rule list, get, create, delete, test, ... +│ ├── fp.py # fp list, get, create, delete +│ ├── hive.py # hive list, get, set, delete, validate, ... +│ ├── output_cmd.py # output list, create, delete +│ ├── artifact.py # artifact upload, list, download +│ ├── payload.py # payload list, upload, download, delete +│ ├── search.py # search run, validate, interactive, saved-queries +│ ├── ioc.py # ioc search, batch-search, enrich +│ ├── event.py # event list, get, timeline +│ ├── detection.py # detection list, get +│ ├── extension.py # extension list, subscribe, unsubscribe, convert-rules, ... +│ ├── installation_key.py # installation-key list, create, delete +│ ├── ingestion_key.py # ingestion-key list, create, delete, configure +│ ├── user.py # user list, invite, remove, permission +│ ├── group.py # group list, create, delete, member, ... +│ ├── api_key.py # api-key list, create, delete +│ ├── org.py # org info, create, delete, rename, config, errors, ... +│ ├── billing.py # billing status, details, invoice, plans +│ ├── stream.py # stream events, detections, audit (spout) +│ ├── replay_cmd.py # replay run, test-rule +│ ├── integrity.py # integrity list, create, delete +│ ├── exfil.py # exfil list, create, delete +│ ├── logging_cmd.py # logging list, create, delete +│ ├── sync.py # sync push, pull, diff +│ ├── ai.py # ai generate-rule, generate-query, ... +│ ├── investigation.py # investigation list, get, create, delete +│ ├── usp.py # usp validate +│ ├── schema.py # schema list, get +│ ├── tag.py # tag list, add, remove, mass-tag +│ ├── task.py # task send, reliable-send, list-reliable +│ ├── endpoint_policy.py # endpoint-policy (isolate, rejoin, seal, unseal) +│ ├── yara.py # yara scan, rules, sources +│ ├── cloud_sensor.py # cloud-sensor list, get, set, delete +│ ├── job.py # job list, get, delete, wait +│ ├── arl.py # arl get +│ ├── spotcheck.py # spotcheck run +│ ├── secret.py # secret list, get, set, delete (NEW) +│ ├── lookup.py # lookup list, get, set, query, delete (NEW) +│ ├── playbook.py # playbook list, get, set, delete (NEW) +│ ├── adapter.py # adapter list, get, set, delete (NEW) +│ ├── sop.py # sop list, get, set, delete (NEW) +│ ├── note.py # note list, get, set, delete (NEW) +│ ├── audit.py # audit list +│ └── help_cmd.py # help, discover, cheatsheet, schema +tests/ +├── unit/ +│ ├── __init__.py +│ ├── conftest.py +│ ├── test_cli_commands.py +│ ├── test_config.py +│ ├── test_client.py +│ ├── test_output.py +│ ├── test_errors.py +│ ├── test_sdk_organization.py +│ ├── test_sdk_sensor.py +│ ├── test_sdk_dr_rules.py +│ ├── test_sdk_hive.py +│ ├── test_sdk_search.py +│ ├── test_sdk_configs.py +│ └── ... +└── integration/ + ├── __init__.py + ├── conftest.py # Integration fixtures with cleanup + ├── test_auth.py + ├── test_sensor.py + ├── test_rules.py + ├── test_hive.py + ├── test_outputs.py + ├── test_artifacts.py + ├── test_search.py + ├── test_extensions.py + ├── test_users.py + ├── test_api_keys.py + ├── test_installation_keys.py + ├── test_ingestion_keys.py + ├── test_sync.py + ├── test_replay.py + ├── test_stream.py + ├── test_ai.py + ├── test_billing.py + ├── test_groups.py + ├── test_org_management.py + ├── test_usp.py + ├── test_integrity.py + ├── test_exfil.py + ├── test_logging.py + ├── test_yara.py + ├── test_jobs.py + └── test_cli_e2e.py # End-to-end CLI tests +``` + +- [ ] Create this directory structure (remove all v1 modules) +- [ ] Each command module auto-registers its click group + +### 2.3 Clean Break from v1 +This is a full v2.0.0 rewrite with no backwards compatibility requirement: +- [ ] v2 code replaces v1 code directly in the `limacharlie/` package (no `v2/` subpackage) +- [ ] All v1 modules (Manager.py, Sensor.py, etc.) are removed +- [ ] Entry point `limacharlie` runs the new Click-based CLI +- [ ] SDK classes available as `limacharlie.sdk.*` (e.g., `from limacharlie.sdk.organization import Organization`) +- [ ] No fallback to v1 CLI, no `limacharlie-v1` entry point + +--- + +## 3. Authentication & Configuration + +### 3.1 Credential Storage +- [ ] Same file location: `~/.limacharlie` (YAML format) +- [ ] Support named environments/profiles: `limacharlie auth use-env production` +- [ ] Environment variables: `LC_OID`, `LC_API_KEY`, `LC_UID`, `LC_CURRENT_ENV`, `LC_CREDS_FILE`, `LC_EPHEMERAL_CREDS` +- [ ] Ephemeral mode (no disk writes) via `LC_EPHEMERAL_CREDS=1` +- [ ] File permissions enforced at 600 + +### 3.2 Auth Commands +- [ ] `limacharlie auth login` - Interactive login (OAuth or API key) +- [ ] `limacharlie auth login --api-key --oid ` - Non-interactive API key login +- [ ] `limacharlie auth login --uid --api-key ` - User-scoped API key login +- [ ] `limacharlie auth logout` - Clear stored credentials +- [ ] `limacharlie auth whoami` - Show current identity, permissions, accessible orgs +- [ ] `limacharlie auth test [--permissions perm1,perm2]` - Test current auth and optional specific permissions +- [ ] `limacharlie auth use-env ` - Switch named environment +- [ ] `limacharlie auth list-envs` - List configured environments +- [ ] `limacharlie auth use-org ` - Set default organization (resolves names to OIDs) +- [ ] `limacharlie auth list-orgs [--filter ]` - List accessible organizations + +### 3.3 Client Features +- [ ] Automatic JWT generation and refresh +- [ ] Retry logic: 3 retries with exponential backoff for 429/504 +- [ ] Rate limit awareness: log warnings on rate limit headers +- [ ] Request debugging via `--debug` (prints curl-equivalent commands) +- [ ] User-Agent header: `limacharlie-cli/2.0.0 python/3.x` +- [ ] Idempotent key support for safe retries on write operations + +--- + +## 4. SDK Core Classes + +### 4.1 Client +- [ ] `limacharlie.Client(oid, api_key, uid, environment, jwt, ...)` +- [ ] Automatic credential resolution: explicit params > env vars > config file +- [ ] Thread-safe JWT management with automatic refresh +- [ ] Request/response logging for debugging +- [ ] Rate limit tracking and backoff +- [ ] Context manager support (`with Client(...) as client:`) + +### 4.2 Organization +- [ ] `Organization(client)` - Main entry point for all org-scoped operations +- [ ] Properties: `oid`, `name`, `info`, `urls` +- [ ] Methods for all org-level operations (sensors, rules, hives, etc.) +- [ ] Lazy-loaded cached properties for org info and URLs + +### 4.3 Sensor +- [ ] `Sensor(organization, sid)` - Represents a single sensor +- [ ] Properties: `sid`, `hostname`, `platform`, `architecture`, `external_ip`, `internal_ip`, `is_online`, `is_isolated`, `tags`, `version`, `enrollment_time`, `last_seen` +- [ ] Platform helpers: `is_windows`, `is_linux`, `is_macos`, `is_chrome` +- [ ] Task methods: `task()`, `request()`, `simple_request()` +- [ ] Tag methods: `add_tag()`, `remove_tag()`, `get_tags()` +- [ ] Network methods: `isolate()`, `rejoin()`, `is_isolated` +- [ ] Lifecycle methods: `delete()`, `seal()`, `unseal()` +- [ ] Event methods: `get_events()`, `get_timeline()`, `get_overview()` + +### 4.4 Hive +- [ ] `Hive(organization, hive_name, partition_key=None)` - Key-value store +- [ ] `HiveRecord` - Record with data, metadata, etag support +- [ ] Methods: `list()`, `get()`, `set()`, `delete()`, `validate()`, `rename()` +- [ ] Transaction support: `update_tx(callback)` with automatic etag retry +- [ ] Batch operations: `batch().get().set().delete().execute()` + +### 4.5 Search +- [ ] `Search(organization)` - LCQL query execution +- [ ] Methods: `validate()`, `estimate()`, `execute()`, `execute_streaming()` +- [ ] Iterator-based pagination for large result sets +- [ ] Progress callback support +- [ ] Saved query management: `list_saved()`, `get_saved()`, `create_saved()`, `delete_saved()` + +### 4.6 Spout (Real-time Streaming) +- [ ] `Spout(organization, data_type, filters=...)` - WebSocket streaming +- [ ] Configurable filters: investigation_id, tags, categories, sensor_ids +- [ ] Auto-reconnect with exponential backoff +- [ ] Queue-based buffering with configurable max +- [ ] Context manager: `with Spout(...) as spout: for event in spout: ...` +- [ ] Future results tracking for sensor tasking + +### 4.7 Configs (Infrastructure-as-Code) +- [ ] `Configs(organization)` - Configuration sync +- [ ] `fetch(components)` - Download current config +- [ ] `push(config, components, force=False, dry_run=False)` - Upload config +- [ ] `diff(config, components)` - Show differences +- [ ] Component selection: rules, fps, outputs, integrity, exfil, logging, artifacts, extensions, org_configs, hives, installation_keys, yara + +### 4.8 AI Generation (NEW) +- [ ] `AI(organization)` - AI-powered generation +- [ ] `generate_dr_rule(description)` - Generate D&R rule from natural language +- [ ] `generate_detection(description)` - Generate detection component +- [ ] `generate_response(description)` - Generate response component +- [ ] `generate_lcql(description)` - Generate LCQL query from natural language +- [ ] `generate_sensor_selector(description)` - Generate bexpr selector +- [ ] `generate_playbook(description)` - Generate Python playbook +- [ ] `summarize_detection(detection_data)` - Summarize a detection + +--- + +## 5. Command Groups & Commands + +### Organization Commands - `limacharlie org` +- [ ] `org info` - Get organization details (sensor count, version, quotas, name) +- [ ] `org list` - List accessible organizations (with --filter support) +- [ ] `org create --location [--template ]` - Create new org +- [ ] `org delete --confirm ` - Delete organization (two-step) +- [ ] `org rename ` - Rename organization +- [ ] `org config get []` - Get org configuration value(s) +- [ ] `org config set ` - Set org configuration value +- [ ] `org urls` - Get service URLs for organization +- [ ] `org quota set ` - Set sensor quota +- [ ] `org stats` - Get usage statistics +- [ ] `org errors [--dismiss ]` - List/dismiss org errors +- [ ] `org mitre-report` - Get MITRE ATT&CK coverage report +- [ ] `org schema [--event-type ] [--platform ]` - Get event schemas/ontology +- [ ] `org runtime-metadata [--entity-type ] [--entity-name ]` - Get runtime metadata +- [ ] `org check-name ` - Check if organization name is available + +### Sensor Commands - `limacharlie sensor` +- [ ] `sensor list [--selector ] [--limit ] [--online-only] [--with-ip ] [--with-hostname ]` - List sensors with rich filtering +- [ ] `sensor get ` - Get sensor details +- [ ] `sensor delete --confirm` - Delete sensor +- [ ] `sensor online ` - Check if sensor is online +- [ ] `sensor wait-online --timeout ` - Wait for sensor to come online +- [ ] `sensor upgrade [--selector ]` - Upgrade sensors to latest version across fleet +- [ ] `sensor set-version --version ` - Set sensor version/branch for organization +- [ ] `sensor export [--selector ]` - Export full sensor manifest as JSON/CSV +- [ ] `sensor dump --confirm` - Trigger full memory dump on sensor (DESTRUCTIVE/HEAVY) +- [ ] `sensor sweep --config ` - Run host sweep/scan on sensor + +### Tag Commands - `limacharlie tag` +- [ ] `tag list [--sensor ]` - List all tags or tags for a sensor +- [ ] `tag add [--ttl ]` - Add tag to sensor +- [ ] `tag remove ` - Remove tag from sensor +- [ ] `tag find ` - Find all sensors with a tag +- [ ] `tag mass-add --selector --tag [--ttl ]` - Bulk tag sensors +- [ ] `tag mass-remove --selector --tag ` - Bulk untag sensors + +### Endpoint Policy Commands - `limacharlie endpoint-policy` +- [ ] `endpoint-policy isolate --confirm` - Isolate sensor from network (DESTRUCTIVE) +- [ ] `endpoint-policy rejoin --confirm` - Rejoin sensor to network (DESTRUCTIVE) +- [ ] `endpoint-policy status ` - Check isolation status +- [ ] `endpoint-policy seal ` - Seal sensor +- [ ] `endpoint-policy unseal ` - Unseal sensor + +### Sensor Tasking Commands - `limacharlie task` +- [ ] `task send [--investigation-id ]` - Send task to sensor (fire-and-forget) +- [ ] `task request [--timeout ]` - Send task and wait for response +- [ ] `task reliable-send ` - Guaranteed delivery task +- [ ] `task reliable-list ` - List pending reliable tasks +- [ ] `task reliable-delete ` - Cancel reliable task + +### D&R Rule Commands - `limacharlie rule` +- [ ] `rule list [--namespace ]` - List D&R rules (namespace: general, managed, service) +- [ ] `rule get [--namespace ]` - Get rule details +- [ ] `rule create --detect --respond [--namespace ] [--enabled] [--ttl ] [--replace]` - Create/replace rule +- [ ] `rule create --input-file ` - Create rule from file +- [ ] `rule update --detect --respond [--namespace ]` - Update existing rule +- [ ] `rule delete [--namespace ]` - Delete rule +- [ ] `rule test --events [--trace]` - Test rule against sample events +- [ ] `rule replay --start