name: janus-ingestor-creation description: Use this skill for Janus requests to design, add, or adjust source ingestors/parsers for live APIs or local files, including Mythic, Ghostwriter, Cobalt Strike REST, Outflank implant logs, new C2 telemetry sources, parser normalization, pull/load CLI wiring, source metadata, retention policy handling, and Docker janus-cli integration.
Janus Ingestor Creation
Overview
Use this skill when Janus needs to ingest a new telemetry source or change how an existing source is pulled, loaded, normalized, or wired into the CLI.
Start from Janus's existing ingest pipeline. Do not create a parallel pipeline unless the user explicitly asks for one.
Workflow
- State the source and mode in one sentence:
- live API pull
- local file/directory load
- hybrid pull plus local normalization
- Read the core ingest path first:
janus.pyCore/models.pyCore/io.pyCore/output_rule.pyConfig/janus.example.ymldocs/architecture.md
- If
janus-clishould expose the ingestor, also read:cmd/janus-cli/config.gocmd/janus-cli/main.gocmd/janus-cli/status.gocmd/janus-cli/docker.go
- Read the closest existing source implementation:
- Mythic live API:
Parsers/Mythic/mythic_pull.py - Partial/local Mythic:
Parsers/Mythic/partial_data_adapter.py - Ghostwriter live/export:
Parsers/Ghostwriter/ghostwriter_pull.py,Parsers/Ghostwriter/main.py - Cobalt Strike REST live API:
Parsers/CobaltStrike/cobalt_strike_rest.py - Outflank local logs:
Parsers/Outflank/outflank_log.py
- Mythic live API:
- Inspect the provided sample data, client, schema, or API docs before asking the user. Ask only for missing product intent or an undiscoverable endpoint/schema detail.
- Implement the smallest source-specific parser that preserves the canonical Janus event model.
For the detailed implementation checklist and source-mode guidance, read references/ingestor-patterns.md.
Event Model Rules
- Normalize all sources into
TaskEventandResultEvent. - Join task/result events by
(operation_id, task_id). - Use
normalize_timestamp()for all timestamps. - Keep parser-specific quirks in the parser module, not in analyzers.
- For string source IDs, derive stable positive integer IDs, and preserve the raw source task ID in
c2_task_idwhen available. - Emit conservative
statusvalues:- Use
success/erroronly when the source provides reliable status or a narrowly documented inference. - Use
unknownwhen status fidelity is weak.
- Use
- Apply
arguments_ruleandoutput_rulebefore writingevents.ndjson. - Record parser quality counters in
bundle.json: row counts, skipped counts, invalid timestamps, fallback IDs, status counts, and source provenance.
Integration Rules
- Put new parser code under
Parsers/<Source>/; do not overwrite or repurpose existing ingestors. - Keep source identifiers stable and lowercase, such as
mythic,ghostwriter,cobaltstrike-rest, oroutflank. - Add explicit Python CLI support for the new source or loader in
janus.py. - Add Go wrapper support when the source should work through
janus-cli pullorjanus-cli run. - Update config examples, status/config output, README usage, and architecture/FAQ docs when behavior is user-facing.
- For live APIs, add auth/preflight behavior and TLS defaults consistent with existing sources.
- For local files, document Docker mount assumptions;
janus-clinormally exposes./outand./Configto the container.
Validation
Always run at least one real CLI/container path after implementation:
- Parser-level import or focused unit test.
- Source load/pull into
events.ndjsonandbundle.json. analyze --allagainst the generated events.htmlreport generation.go testforcmd/janus-cliwhen Go wrapper code changed.
Report source fidelity limits in the final answer, especially for status inference and partial/local datasets.