Commit 360a9c9
Feature/detectors (vsilent#103)
* ebpf files
* refactoring, ebpf / containers
* feat(cli): add clap subcommands (serve/sniff) + sniff config
- Add clap 4 for CLI argument parsing
- Refactor main.rs: dispatch to serve (default) or sniff subcommand
- Create src/cli.rs with Cli/Command enums
- Create src/sniff/config.rs with SniffConfig (env + CLI args)
- Add new deps: clap, async-trait, reqwest, zstd
- Update .env.sample with sniff + AI provider config vars
- 12 unit tests (7 CLI parsing + 5 config loading)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(sniff): log source discovery + database persistence
- Create src/sniff/discovery.rs: LogSource, LogSourceType, discovery
functions for system logs, Docker containers, and custom paths
- Create src/database/repositories/log_sources.rs: CRUD for log_sources
and log_summaries tables (follows existing alerts repository pattern)
- Add log_sources and log_summaries tables to init_database()
- Export docker module from lib.rs for reuse by sniff discovery
- 14 unit tests (8 discovery + 6 repository)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(sniff): log reader trait + File/Docker/Journald implementations
- Create src/sniff/reader.rs with LogReader async trait and LogEntry struct
- FileLogReader: byte offset tracking, incremental reads, log rotation detection
- DockerLogReader: bollard-based container log streaming with timestamp filtering
- JournaldReader: journalctl subprocess (Linux-gated with #[cfg(target_os = "linux")])
- Add futures-util dependency for Docker log stream consumption
- 10 unit tests covering read, incremental, truncation, empty lines, metadata
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(sniff): AI log analysis with OpenAI and pattern backends
- Create src/sniff/analyzer.rs with LogAnalyzer trait
- OpenAiAnalyzer: single client for OpenAI/Ollama/vLLM/any compatible API
sends batched logs to /chat/completions, parses structured JSON response
- PatternAnalyzer: fallback local analyzer using regex-free pattern matching
detects error spikes, counts errors/warnings without external AI
- LogSummary and LogAnomaly types with serialization support
- JSON response parsing with graceful handling of partial LLM output
- 16 unit tests (prompt building, JSON parsing, pattern analysis, serialization)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(sniff): consume mode — zstd compression, dedup, log purge
- Create src/sniff/consumer.rs with LogConsumer
- FNV hashing deduplication with configurable capacity (100k entries)
- zstd compression (level 3) with timestamped archive files
- File purge via truncation (preserves fd for syslog daemons)
- Docker log purge via /var/lib/docker/containers/ JSON log truncation
- Full consume pipeline: deduplicate → compress → purge → report stats
- ConsumeResult tracks entries_archived, duplicates_skipped, bytes_freed
- 13 unit tests (hashing, dedup, compression, purge, full pipeline)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(sniff): reporter + orchestrator loop
- Reporter: converts LogSummary/LogAnomaly into Alerts using existing
AlertManager infrastructure (route_by_severity, NotificationChannel)
- SniffOrchestrator: full discover → read → analyze → report → consume
pipeline with continuous and one-shot modes
- Wire up run_sniff() in main.rs to use SniffOrchestrator
- Add events, rules, alerting, models modules to binary crate
- 7 new tests (reporter: 5, orchestrator: 3)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(sniff): REST API for log sources and summaries
- GET /api/logs/sources — list discovered log sources
- POST /api/logs/sources — manually add a custom log source
- GET /api/logs/sources/{path} — get a single source
- DELETE /api/logs/sources/{path} — remove a source
- GET /api/logs/summaries — list AI summaries (optional source_id filter)
- Register routes in configure_all_routes
- 7 tests covering all endpoints
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: update CHANGELOG and README for sniff feature
- CHANGELOG: document all sniff additions (discovery, readers, AI
analysis, consumer, reporter, orchestrator, REST API, deps)
- README: add log sniffing to key features, architecture diagram,
project structure, CLI usage examples, REST API examples,
and completed tasks list
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: remove task files from repo and gitignore
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: add curl-based binary installation
- install.sh: POSIX shell installer — detects Linux x86_64/aarch64,
downloads from GitHub Releases, verifies SHA256, installs to
/usr/local/bin
- release.yml: GitHub Actions workflow — builds Linux binaries on tag
push using cross, creates release with tarballs + checksums
- README: add curl install one-liner to Quick Start
Usage:
curl -fsSL https://raw.githubusercontent.com/vsilent/stackdog/dev/install.sh | sudo bash
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: fix ML module status — stub infrastructure, not in progress
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(cli): add --ai-model and --ai-api-url flags to sniff command
- Add --ai-model flag to specify AI model (e.g. qwen2.5-coder:latest)
- Add --ai-api-url flag to specify API endpoint URL
- Recognize "ollama" as AI provider alias (maps to OpenAI-compatible client)
- CLI args override env vars for model and API URL
- Log AI model and API URL at startup for transparency
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(sniff): add debug logging and robust LLM JSON extraction
- Add debug/trace logging across entire sniff pipeline:
discovery, reader, analyzer, orchestrator, reporter
- Respect user RUST_LOG env var (no longer hardcoded to info)
- Improve LLM response JSON extraction to handle:
markdown code fences, preamble text, trailing text
- Include raw LLM response in trace logs for debugging parse failures
- Show first 200 chars of failed JSON in error messages
- Add 5 tests for extract_json edge cases
Usage: RUST_LOG=debug stackdog sniff --once ...
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(alerting): implement real Slack webhook notifications
- Add --slack-webhook CLI flag to sniff command
- Read STACKDOG_SLACK_WEBHOOK_URL env var (CLI overrides env)
- Implement actual HTTP POST to Slack incoming webhook API
- Build proper JSON payloads with serde_json (color-coded by severity)
- Add reqwest blocking feature for synchronous notification delivery
- Wire NotificationConfig through SniffConfig → Orchestrator → Reporter
- Add STACKDOG_WEBHOOK_URL env var support
- Update .env.sample with notification channel examples
- Add 3 tests for Slack webhook config (CLI, env, override priority)
Usage:
stackdog sniff --once --slack-webhook https://hooks.slack.com/services/T/B/xxx
# or via env:
export STACKDOG_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T/B/xxx
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update docker.yml
* ci: upgrade deprecated GitHub Actions to v4
- actions/cache v2 → v4
- actions/upload-artifact v2 → v4
- actions/download-artifact v2 → v4
- actions/checkout v2 → v4
- docker/build-push-action v1 → v6 (+ docker/login-action v3)
- github/codeql-action/upload-sarif v1 → v3
Fixes: deprecated action versions causing workflow failures
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: modernize Docker CICD workflow
- Replace deprecated actions-rs/* with dtolnay/rust-toolchain + cargo commands
- Fix broken rustfmt/clippy steps (were using wrong action parameters)
- Use Swatinem/rust-cache for simpler, faster dependency caching
- Use ubuntu-latest runners instead of self-hosted
- Add Docker Buildx for improved image builds
- Trigger on PRs to main and dev (pushes :latest on every build)
- Use npm ci for deterministic frontend installs
- Add artifact retention-days: 1 to save storage
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* build: switch to musl targets and rustls for portable binaries
- reqwest: use rustls-tls instead of native-tls (no OpenSSL dependency)
- release.yml: build x86_64/aarch64-unknown-linux-musl (static binaries)
- Dockerfile: update debian:buster-slim → bookworm-slim, drop libpq-dev
Statically linked binaries work on any Linux distro including Alpine.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: add pre-commit hook and apply cargo fmt
Add .githooks/pre-commit that runs:
- cargo fmt --all --check (strict, blocks commit)
- cargo clippy (shows warnings, blocks on compile errors)
Enable with: git config core.hooksPath .githooks
Also applies cargo fmt --all to fix existing formatting across codebase.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: resolve all clippy warnings
- Remove unused imports across 17 files
- Prefix unused variables/fields with underscore
- Implement Default trait instead of inherent default() methods (dedup, threat_scorer)
- Implement FromStr trait instead of inherent from_str() methods (AiProvider, LogSourceType)
- Replace Iterator::last() with next_back() on DoubleEndedIterator
- Derive Default for EbpfLoader instead of manual impl
- Remove useless .into() conversion in database connection
- Wrap too-many-arguments functions with param structs (SniffArgs, CreateLogSummaryParams)
- Replace filter_map(Some(...)) with map(...) in build_readers
- Replace manual find loop with Iterator::find
- Collapse nested if-let in signature_matcher
- Gate program_to_tracepoint with cfg for Linux+ebpf only
- Move api module to library crate, fix binary to import from library
- Fix pre-existing test_get_alerts_empty to init database
- Use std::io::Error::other() instead of Error::new(Other, e)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: use _pid consistently in get_process_comm
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: resolve clippy errors in Linux-only firewall modules
- Remove unused imports in nftables.rs, quarantine.rs
- Replace inherent to_string() with Display trait for NfTable
- Remove needless borrows in .args() calls (iptables.rs, nftables.rs)
- Prefix unused variables with underscore (response.rs)
- Add error() getter to ResponseLog
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: remove redundant to_string() in format! args
NfTable implements Display, so format! uses it directly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: convert NfTable to string before passing to args()
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: bump VERSION.md to 0.2.0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: resolve warnings in tests and examples
- Remove unused imports (AlertSeverity, AlertType, anyhow::Result, SyscallEvent, SyscallType)
- Prefix unused variables with underscore
- Fix EbpfLoader::default() test (returns value, not Result)
- Fix KernelVersionTooLow fields to use String not integer literals
- Remove unnecessary mut on enricher variables
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: restore mutable enricher in enrichment tests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: align test mutability and silence unused ptrace events var
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(tests): clean remaining all-target warnings and invalid literal
- remove useless UID >= 0 assertion (u32)
- replace invalid u16 port overflow test with type-safety test
- remove redundant serde_json import
- fix cfg-sensitive unused vars in enrichment tests
- clean monitor test vars in syscall monitor unit tests
- remove unused TestRule in rules engine tests
- use from_ref instead of cloned slice in sniff discovery test
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: restore used enrichment vars and silence ptrace unused vars
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: handle non-linux unused vars in enrichment tests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test: fix ebpf loader creation assertion for linux builds
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test: use valid 64-char hex container ID in enrichment test
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: fallback to npm install when web lockfile is missing
Use npm ci only when web/package-lock.json exists to avoid EUSAGE in CI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* web: add webpack config with TS entrypoint for dashboard build
Fix CI frontend build fallback to default ./src entry by defining explicit
entry ./src/index.tsx and html template.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* web: fix dashboard import paths and TypeScript build errors
- Correct component imports from ../../services|types to ../services|types
- Fix react-bootstrap Alert alias in ContainerList
- Add explicit typed mappings for alert/container badge variants
- Type websocket stats callback payload
- Import fireEvent in ThreatMap tests
- Improve WebSocket test mock shape to satisfy TS
- Expose ApiService.api for existing tests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* log: show API URL instead of dashboard bind address
- Replace misleading "Web Dashboard" startup line
- Show user-facing API URL and map 0.0.0.0 -> 127.0.0.1 for display
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* web: default API/WS endpoints to APP_PORT or 5555
- Inject APP_PORT and REACT_APP_API_PORT into webpack env
- API service default: http://localhost:${port}/api (port from env, fallback 5555)
- WS service default: ws://localhost:${port}/ws (port from env, fallback 5555)
Fixes frontend trying to connect to hardcoded port 5000.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* web: normalize container API payloads to prevent runtime crashes
Handle both snake_case and camelCase fields for containers API responses,
with safe defaults for missing nested fields (securityStatus/networkActivity).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* web: fix threat statistics endpoint path
Use /threats/statistics to match backend routes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* web: guard ThreatMap against missing stats buckets
Handle absent byType/bySeverity in API responses to prevent runtime
Object.entries(undefined) crashes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* web: restore CSS injection and degrade gracefully without WS endpoint
- Use style-loader + css-loader for .css files (fix dashboard styling)
- Add css/style loader deps to web package
- WebSocket service now falls back to REST-only mode when /ws is unavailable
to avoid noisy reconnect/error spam in dev
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* web: add left sidebar navigation to dashboard layout
- Introduce Sidebar component with Overview/Threats/Alerts/Containers links
- Update App layout to include sidebar + main dashboard content
- Add section anchors in Dashboard for sidebar navigation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* web: move logo to sidebar and add top actions bar
- Move logo into sidebar at 39x39 (30% larger than 30x30)\n- Remove "Stackdog Security Dashboard" header text\n- Add top bar with right-aligned actions menu button (...)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* install: fallback when latest release is missing
- Handle GitHub /releases/latest 404 gracefully\n- Fallback to most recent release entry\n- Improve install usage examples to main branch URL
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: avoid panic on malformed .env
- Make .env loading non-fatal in main\n- Print warning and continue with existing environment\n- Ensures stackdog --help works even with malformed .env
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: update README and changelog for installer/env fixes
- README: switch install script examples to main and v0.2.1\n- CHANGELOG: document non-fatal .env loading and installer fallback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Limit sniff analyzer prompts
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add live mail abuse guard
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* iptables & nftables
* multiple updates, eBPF, container API quality is improved
* tests, ip_ban engine implemented, frontend dashboard improvements
* logs, containers in ui, ports, ws
* context.to_string()
* clippy fix
* clippy fix
* clippy fix
* ip_ban::engine::tests
* GLIBC_2.39 not found fix, using musl
* docker files
* multi stage build
* The problem was cross build reusing the default target directory, which already contained host-built build-script binaries. Now musl build uses its own isolated target di
* mount docker.sock to stackdog container
* Audit, analyze syslog, new detectors, sniff command enriched
* Audit, analyze syslog, new detectors, sniff command enriched
---------
Co-authored-by: vsilent <jabberroid@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 10d00d8 commit 360a9c9
File tree
181 files changed
+13559
-8259
lines changed- .githooks
- .github/workflows
- docker
- backend
- prod
- ui
- docs
- tasks
- ebpf
- .cargo
- src
- examples
- migrations
- 00000000000000_create_alerts
- 00000000000003_create_ip_offenses
- src
- alerting
- api
- baselines
- collectors
- ebpf
- programs
- correlator
- database
- models
- repositories
- detectors
- docker
- events
- firewall
- ip_ban
- ml
- models
- models/api
- response
- rules
- sniff
- tests
- api
- collectors
- events
- firewall
- web
- src
- components
- __tests__
- services
- __tests__
- types
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
181 files changed
+13559
-8259
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| |||
41 | 41 | | |
42 | 42 | | |
43 | 43 | | |
44 | | - | |
| 44 | + | |
45 | 45 | | |
46 | 46 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
7 | | - | |
| 5 | + | |
8 | 6 | | |
9 | | - | |
10 | | - | |
| 7 | + | |
11 | 8 | | |
12 | 9 | | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
17 | 13 | | |
18 | | - | |
19 | | - | |
| 14 | + | |
20 | 15 | | |
21 | | - | |
22 | | - | |
| 16 | + | |
| 17 | + | |
23 | 18 | | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | 19 | | |
| 20 | + | |
28 | 21 | | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
46 | 27 | | |
47 | 28 | | |
48 | | - | |
49 | | - | |
| 29 | + | |
50 | 30 | | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
| 31 | + | |
| 32 | + | |
64 | 33 | | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
| 34 | + | |
| 35 | + | |
70 | 36 | | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
96 | 47 | | |
97 | | - | |
| 48 | + | |
98 | 49 | | |
99 | 50 | | |
100 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
101 | 56 | | |
102 | | - | |
103 | 57 | | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
| 58 | + | |
121 | 59 | | |
122 | 60 | | |
123 | | - | |
124 | | - | |
| 61 | + | |
| 62 | + | |
125 | 63 | | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
| 64 | + | |
| 65 | + | |
130 | 66 | | |
131 | | - | |
132 | | - | |
| 67 | + | |
| 68 | + | |
133 | 69 | | |
134 | | - | |
| 70 | + | |
135 | 71 | | |
| 72 | + | |
136 | 73 | | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
142 | 78 | | |
143 | | - | |
144 | | - | |
| 79 | + | |
| 80 | + | |
145 | 81 | | |
146 | | - | |
| 82 | + | |
147 | 83 | | |
148 | | - | |
149 | | - | |
| 84 | + | |
| 85 | + | |
150 | 86 | | |
151 | | - | |
152 | | - | |
| 87 | + | |
| 88 | + | |
153 | 89 | | |
154 | | - | |
155 | | - | |
| 90 | + | |
| 91 | + | |
156 | 92 | | |
157 | 93 | | |
158 | 94 | | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | | - | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | | - | |
| 23 | + | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
| 40 | + | |
39 | 41 | | |
40 | 42 | | |
41 | 43 | | |
42 | 44 | | |
43 | 45 | | |
44 | | - | |
| 46 | + | |
45 | 47 | | |
46 | 48 | | |
47 | 49 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
36 | 37 | | |
| 38 | + | |
| 39 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
10 | 22 | | |
11 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
12 | 34 | | |
13 | 35 | | |
14 | 36 | | |
| |||
66 | 88 | | |
67 | 89 | | |
68 | 90 | | |
| 91 | + | |
69 | 92 | | |
70 | 93 | | |
71 | 94 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | | - | |
| 51 | + | |
| 52 | + | |
52 | 53 | | |
53 | 54 | | |
54 | 55 | | |
55 | 56 | | |
56 | 57 | | |
57 | 58 | | |
| 59 | + | |
58 | 60 | | |
59 | 61 | | |
60 | 62 | | |
| |||
78 | 80 | | |
79 | 81 | | |
80 | 82 | | |
| 83 | + | |
| 84 | + | |
81 | 85 | | |
82 | 86 | | |
83 | 87 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
| 3 | + | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
0 commit comments