Commit Graph

1211 Commits

Author SHA1 Message Date
CarterPerez-dev b57e20d8fa feat(rube): M3 gadget scanner - reflection-based sink discovery with reachability filter
Walks the live class graph and classifies auto-invoked methods along the
gated/ungated dispatch axis. Marshal calls respond_to? before invoking
marshal_load and _load, while hash, eql?, <=>, []= and to_s are dispatched
blind, so a class can be dead as a Marshal entry point and live as a #hash
entry point.

Rediscovers Gem::Requirement#marshal_load, Gem::Version#marshal_load and
Gem::Specification._load with source locations, from reflection alone, with no
class names hardcoded anywhere in the scanner.

A new control asserts the M1 parser and the M3 scanner agree. The parser reads
bytes off a payload, the scanner walks the class graph, neither consults the
other, and every sink the parser finds in a real Gem::Requirement payload is
one the scanner independently located. Two routes to the same fact.

Raw output was unusable at 163 ungated candidates dominated by to_s and hash,
which nearly every class defines. The reachability predicate from the research
narrows that to methods that are zero-arity AND touch instance state, cutting
163 to 12 and keeping 7.4 percent. Gated sinks are always reachable.

Two corrections found while building the predicate:

RubyVM::AbstractSyntaxTree.of does not work on Ruby 4.0. It raises
'cannot get AST for ISEQ compiled by prism' because prism is now the default
parser. Any tool reaching for that API on modern Ruby is broken. Replaced with
Prism, which ships as a default gem.

The literal reads-its-own-ivars predicate is too narrow. Gem::Requirement#hash
calls the requirements attr_reader rather than @requirements, so an instance
variable check reports false on a method that plainly operates on instance
state. Widened to instance variable reads OR implicit-self calls.

55 tests, 112 assertions, 0 failures across both suites.
2026-07-26 09:57:03 -04:00
CarterPerez-dev a4ca6760d1 feat(rube): M2 version matrix - executed gadget compatibility across six Rubies
Probes six pinned Ruby images with no network and renders a compatibility
matrix for the deserialization gadget surface. Reproducible with just matrix.

The matrix carries three controls, because a table that reports one value
everywhere cannot be distinguished from a probe that always returns the same
answer. Two axes must show more than one state, and the ERB guard column is
cross-checked against the published CVE-2026-41316 affected ranges. That third
control is the load-bearing one: the probe reads source and knows nothing about
NVD, and it agrees with the advisory on 6 of 6 images.

Findings recorded in the research docs:

The gadget surface moved rather than shrank. Net::WriteAdapter is reachable at
baseline on Ruby 3.1 and 3.2 and gone from 3.3 onward, which is why vakzz-era
chains needed no preloaded net/http on old Ruby. Gem::URI appears in the same
release that took it away, and Gem::URI reached through an autoloaded
Gem::SpecFetcher is exactly the bootstrap the 2024 chain relies on. One door
closed and another opened in the same version, so a defense reasoning about
the known gadget classes is reasoning about a moving target.

The ERB @_init guard sits only on def_method. def_module and def_class delegate
to it in both vulnerable and patched releases, so one check covers all three.
The first probe measured all three independently and reported the delegates as
unguarded even on patched erb 6.0.1.1. That was the probe being wrong, not the
patch being incomplete, and it is corrected here.

Marshal stream format is 4.8 on every image, so the M1 parser applies across
the whole range unchanged. make and git are absent from every slim image, so
rake is the only exec binary present on that family.
2026-07-26 09:35:53 -04:00
CarterPerez-dev f5196252e9 feat(rube): M1 Marshal stream parser - inspect payloads without deserializing
Scaffolds the Ruby deserialization security lab and lands its defensive core
first: a parser that extracts structure, referenced class names, and gadget
sinks from a Marshal stream without ever calling Marshal.load.

Sinks are classified along the gated/ungated dispatch axis. Marshal checks
respond_to? before invoking marshal_load and _load, while hash, eql?, <=> and
[]= are dispatched blind, so the same class can be dead as a Marshal entry
point and live as a #hash entry point.

Object links are ZERO-indexed. Ruby's Marshal format documentation says
one-indexed and is wrong: a self-referential array dumps as 04 08 5b 06 40 00
with the trailing 00 linking to the outermost object. Written against observed
bytes rather than the docs.

Validation rejects truncated streams, unsupported version bytes, unknown type
tags, out-of-bounds object links and symlinks, oversized fixnum widths,
trailing bytes, and nesting past a configurable depth limit.

A negative-control script accompanies the suite and caught a test that was
passing vacuously: the TracePoint oracle watched :c_call, but Marshal.load is
a Ruby-level method in Ruby 4.0 (<internal:marshal>:33) and fires :call, so
the test could never have failed. The suite now asserts the oracle observes a
real Marshal.load before the negative assertion is allowed to mean anything.

Gem manifest is an explicit allowlist rather than git ls-files, so the
deliberately vulnerable target cannot be swept into a published gem later.

34 tests, 62 assertions, 0 failures. 52/52 corpus round-trip. gem build
--strict clean. All execution in ruby:4.0-slim with --network none.
2026-07-26 09:32:14 -04:00
Carter Perez 7822ef1d49
Merge pull request #314 from CarterPerez-dev/dependabot/npm_and_yarn/PROJECTS/intermediate/siem-dashboard/frontend/axios-1.18.0
chore(deps): bump axios from 1.16.0 to 1.18.0 in /PROJECTS/intermediate/siem-dashboard/frontend
2026-07-26 06:55:18 -04:00
dependabot[bot] f43a839e2d
chore(deps): bump axios
Bumps [axios](https://github.com/axios/axios) from 1.16.0 to 1.18.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.16.0...v1.18.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 00:42:46 +00:00
Carter Perez 30d6078b8e
Merge pull request #313 from CarterPerez-dev/dependabot/npm_and_yarn/PROJECTS/advanced/ai-threat-detection/frontend/axios-1.18.0
chore(deps): bump axios from 1.16.0 to 1.18.0 in /PROJECTS/advanced/ai-threat-detection/frontend
2026-07-20 20:40:45 -04:00
Carter Perez bf4e739f42
Merge pull request #312 from CarterPerez-dev/dependabot/npm_and_yarn/PROJECTS/advanced/honeypot-network/frontend/axios-1.18.0
chore(deps): bump axios from 1.16.0 to 1.18.0 in /PROJECTS/advanced/honeypot-network/frontend
2026-07-20 20:40:40 -04:00
dependabot[bot] 3fc5b15d49
chore(deps): bump axios
Bumps [axios](https://github.com/axios/axios) from 1.16.0 to 1.18.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.16.0...v1.18.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-20 18:24:02 +00:00
dependabot[bot] 7bbdc03504
chore(deps): bump axios in /PROJECTS/advanced/honeypot-network/frontend
Bumps [axios](https://github.com/axios/axios) from 1.16.0 to 1.18.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.16.0...v1.18.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-20 18:24:02 +00:00
Carter Perez 0f7d9a8302
Delete PROJECTS/beginner/simple-vulnerability-scanner/hf_readme.gif 2026-07-19 23:26:24 -04:00
Carter Perez 9760745f15
Update README.md 2026-07-19 23:26:11 -04:00
Carter Perez 0a03f53865
Change demo image in README.md
Updated demo image in README and adjusted badge links.
2026-07-19 23:23:46 -04:00
Carter Perez 4dc2a19bd3
Add files via upload 2026-07-19 23:23:12 -04:00
Carter Perez 583b6b31a4
Update README.md 2026-07-19 23:22:49 -04:00
Carter Perez 2979a0b858
Merge pull request #311 from CarterPerez-dev/project/steganography-multi-tool
Project/steganography multi tool
2026-07-19 03:24:47 -04:00
CarterPerez-dev 80bd617378 style(canary): format config_test.go with golines (max-len 80)
Vertically wrap the long table-driven case literals and one Fatalf call to
satisfy the project's golines linter (max-len 80, reformat-tags), which the CI
Go lint job flagged. Formatting only; no test behavior change.
2026-07-19 03:18:17 -04:00
CarterPerez-dev c319960bbb ci(network-traffic-analyzer): drop ruff preview to keep lint green across versions
The lint job installs ruff unpinned (pip install ruff), which reached 0.15.22
and, under preview = true, promoted the rule-codes-in-selectors diagnostic that
rejects rule codes like E501/S101 in lint.ignore. This project was the only one
with preview enabled. Dropping preview keeps the code-based selectors valid on
every ruff version in play (0.15.1 pre-commit pin, 0.15.7, 0.15.22 CI) and
aligns it with the other Python projects. No rule coverage change.
2026-07-19 03:18:03 -04:00
CarterPerez-dev 7c1fab2240 docs(crypha): add learn/ track and surface the built project (M9)
Add the five-part learn/ folder (overview, concepts, architecture,
implementation, challenges) grounded in docs/research, with the
QR-from-ISO/IEC-18004 Reed-Solomon injection as the showpiece and crypha's
real capacities cited from the binary. Update the root README row from a
Python synopsis to the built Go project with Source Code and Docs links,
matching the nadezhda row.
2026-07-19 03:06:49 -04:00
CarterPerez-dev 908728be50 chore(binary-analysis): update live demo URL and fix prod healthcheck
Point the README live-demo badge at elitenetwork4life.com and drop the
'|| exit 1' from the exec-form HEALTHCHECK CMD, where the shell operator was
never interpreted and only served to confuse the intended behavior.
2026-07-19 02:45:20 -04:00
CarterPerez-dev 97da7fb3a0 feat(canary): add configurable trusted-proxy CIDRs for X-Forwarded-For
RealIP only reads XFF when the immediate peer sits in TRUSTED_PROXY_CIDRS,
so an untrusted client can no longer spoof its source IP while a real client
behind a known reverse proxy still resolves correctly. Parses the
comma-separated list via a knadh/koanf ProviderWithValue callback (blank or
whitespace-only input leaves the built-in default intact), wires the var
through both compose files and .env.example, and adds MYSQL_FAKE_* and
TURNSTILE_SECRET env aliases. Covered by config_test.go.
2026-07-19 02:45:10 -04:00
CarterPerez-dev b705f1ddd1 docs(crypha): add README and DEMO in the house style (M9) 2026-07-19 02:39:19 -04:00
CarterPerez-dev 3f92f93e77 build(crypha): add one-shot installer, goreleaser, CI, and AGPL license (M9) 2026-07-19 02:39:18 -04:00
Carter Perez 44ef05b439
Merge pull request #310 from CarterPerez-dev/dependabot/uv/PROJECTS/advanced/ai-threat-detection/backend/torch-2.13.0
chore(deps): bump torch from 2.10.0 to 2.13.0 in /PROJECTS/advanced/ai-threat-detection/backend
2026-07-19 02:10:25 -04:00
dependabot[bot] bf31b6c7e8
chore(deps): bump torch
Bumps [torch](https://github.com/pytorch/pytorch) from 2.10.0 to 2.13.0.
- [Release notes](https://github.com/pytorch/pytorch/releases)
- [Changelog](https://github.com/pytorch/pytorch/blob/main/RELEASE.md)
- [Commits](https://github.com/pytorch/pytorch/compare/v2.10.0...v2.13.0)

---
updated-dependencies:
- dependency-name: torch
  dependency-version: 2.13.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-17 19:49:32 +00:00
CarterPerez-dev f0e90271e7 feat(crypha): add bubbletea tui wizard over the shared engine (M8)
Guided hide/reveal/capacity wizard in internal/tui as a pure view over internal/engine (no carrier logic): HCL gradient engine, live capacity meter, embed animation, and a secure-options form. Bare crypha on a TTY launches it; piped or --help prints help. Adds engine.Overhead and engine.EnvelopeSize for exact payload-fit preflight (flate pass only, no KDF).
2026-07-16 10:11:33 -04:00
CarterPerez-dev 3b790e5956 feat(crypha): add cobra cli, shared engine, and report layer (M7) 2026-07-15 21:39:26 -04:00
CarterPerez-dev 0ae323eb5d feat(crypha): add qr carrier with reed-solomon error injection (M6)
Reimplements the QR internals needed for the covert channel from
ISO/IEC 18004: the function-module map, format-info parse, data mask,
zigzag placement, and error-correction block de-interleave, plus a
from-scratch Reed-Solomon decoder over GF(2^8) (syndromes, Berlekamp-
Massey, Chien search, and a Vandermonde magnitude solve). skip2 generates
the clean symbol; crypha introspects it and reuses none of its internals.

The payload is hidden as up to floor(t/2) correctable codeword errors per
block in the data region, leaving the error-correction codewords intact,
so any scanner's Reed-Solomon decoder self-heals to the cover and never
sees it. Reveal reads the module grid, RS-decodes each block itself, and
diffs the corrected data against the stego to recover the payload. EC
level is fixed at H; versions 1-10 auto-select by cover and payload size.
Capacity is tens of bytes, so an encrypted envelope (which exceeds it) is
rejected cleanly.

Differentially tested: the extracted codewords match skip2 as valid RS
codewords across all supported versions, and every stego still scans back
to the cover via gozxing at the full injection budget. skip2 is a runtime
dependency (the generator); gozxing is test-only. No toolchain bump; the
go directive stays 1.25.0.
2026-07-15 18:09:38 -04:00
CarterPerez-dev 2c0d3ae409 feat(crypha): add audio and pdf carriers (M4-M5)
M4 audio: 16-bit PCM WAV LSB carrier. Cover input is WAV or FLAC
(FLAC decoded via the mewkiz decoder); output is always 16-bit PCM
WAV. Native FLAC output is deferred. uint32 length-prefix framing
with overflow-safe bounds; in-memory WriteSeeker so the WAV encoder
can seek back and patch chunk sizes through the io.Writer interface.

M5 pdf: three techniques behind one carrier. Attachment (default,
pdfcpu embedded-file, lossless), metadata (base64url payload chunked
across custom Info-dict keys), and append-after-EOF (raw trailing
bytes, O(1) end-seek). Reveal auto-tries all three; technique
selection is exposed via New(Technique). The package disables the
pdfcpu config directory for hermeticity.

Both carriers self-register and are blank-imported in carrier/all.
No toolchain bump (go directive stays 1.25.0).
2026-07-15 06:33:11 -04:00
CarterPerez-dev 5763638006 feat(crypha): add image and zero-width text carriers (M2-M3)
M2 image carrier: LSB embedding in PNG and 24-bit BMP covers via the
mandatory NRGBA conversion (avoids the premultiply LSB-corruption trap on
both encode paths), RGB-only with alpha untouched, uint32 length prefix,
paletted/16-bit/JPEG rejection, Capacity and Sniff, self-registering.

M3 text carrier: encrypted payload hidden as zero-width Unicode
(U+200B/U+2060) appended after cover text, magic + length framing that
survives incidental zero-width in the cover and NFC/NFD/NFKC/NFKD
normalization. Frame extraction consumes exactly to the end of the
carrier-bit stream so nested stego reveals the last-hidden layer.

New internal/carrier/all sentinel blank-imports carriers into the
registry. Adds golang.org/x/image/bmp and (test-only) golang.org/x/text.
2026-07-15 00:27:46 -04:00
CarterPerez-dev b89b57347d feat(crypha): scaffold steganography multi-tool with payload engine (M0-M1)
New beginner-tier Go project (crypha): a multi-format steganography tool that hides an encrypted payload across five carriers (image, audio, QR, zero-width text, PDF) from a cobra CLI and a planned bubbletea TUI.

M0 scaffold: cobra skeleton, config constants, justfile, golangci config. M1 engine spine: internal/bitio (MSB-first bit reader/writer), internal/payload (versioned AEAD envelope: Argon2id KDF, ChaCha20-Poly1305 default / AES-256-GCM alternate, flate compression, CRC32 integrity, header-as-AAD, hostile-parameter hardening), internal/carrier (Carrier interface + self-registering registry).

Verified: go build, go vet, gofmt, golangci-lint (0 issues), go test -race all green; coverage bitio 100% / carrier 91% / payload 88%.
2026-07-14 17:03:34 -04:00
Carter Perez 816dd4506c
Merge pull request #308 from CarterPerez-dev/dependabot/go_modules/PROJECTS/beginner/canary-token-generator/backend/golang.org/x/crypto-0.52.0
chore(deps): bump golang.org/x/crypto from 0.51.0 to 0.52.0 in /PROJECTS/beginner/canary-token-generator/backend
2026-07-10 16:29:41 -04:00
dependabot[bot] e196026071
chore(deps): bump golang.org/x/crypto
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.51.0 to 0.52.0.
- [Commits](https://github.com/golang/crypto/compare/v0.51.0...v0.52.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.52.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-09 21:32:07 +00:00
Carter Perez 474affb52a
Merge pull request #305 from CarterPerez-dev/dependabot/go_modules/PROJECTS/intermediate/security-news-scraper/golang.org/x/net-0.55.0
chore(deps): bump golang.org/x/net from 0.52.0 to 0.55.0 in /PROJECTS/intermediate/security-news-scraper
2026-07-09 17:30:01 -04:00
Carter Perez f2076a74c7
Merge pull request #306 from CarterPerez-dev/dependabot/go_modules/PROJECTS/intermediate/secrets-scanner/golang.org/x/crypto-0.52.0
chore(deps): bump golang.org/x/crypto from 0.51.0 to 0.52.0 in /PROJECTS/intermediate/secrets-scanner
2026-07-09 17:29:53 -04:00
Carter Perez cf09ea10e3
Merge pull request #307 from CarterPerez-dev/dependabot/uv/PROJECTS/intermediate/dlp-scanner/soupsieve-2.8.4
chore(deps): bump soupsieve from 2.8.3 to 2.8.4 in /PROJECTS/intermediate/dlp-scanner
2026-07-09 17:29:45 -04:00
Carter Perez 7a4f8a5792
Update README.md 2026-07-09 17:27:12 -04:00
dependabot[bot] 04bccaf58a
chore(deps): bump soupsieve in /PROJECTS/intermediate/dlp-scanner
Bumps [soupsieve](https://github.com/facelessuser/soupsieve) from 2.8.3 to 2.8.4.
- [Release notes](https://github.com/facelessuser/soupsieve/releases)
- [Commits](https://github.com/facelessuser/soupsieve/compare/2.8.3...2.8.4)

---
updated-dependencies:
- dependency-name: soupsieve
  dependency-version: 2.8.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-09 21:25:59 +00:00
dependabot[bot] 05b08531c6
chore(deps): bump golang.org/x/crypto
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.51.0 to 0.52.0.
- [Commits](https://github.com/golang/crypto/compare/v0.51.0...v0.52.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.52.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-09 21:25:45 +00:00
dependabot[bot] 140a8d7e3e
chore(deps): bump golang.org/x/net
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.52.0 to 0.55.0.
- [Commits](https://github.com/golang/net/compare/v0.52.0...v0.55.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.55.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-09 21:25:41 +00:00
Carter Perez 318e5967be
Merge pull request #304 from CarterPerez-dev/project/security-news-scraper
Project/security news scraper
2026-07-09 17:23:32 -04:00
CarterPerez-dev 874114c351 docs(nadezhda): add TUI screenshot to the README
Center assets/tui.png below the tagline and above the overview, using the house p-align-center image convention. Carries the badge bump to Project #39 and the What it is section heading.
2026-07-09 17:10:41 -04:00
CarterPerez-dev d511634ccd docs(nadezhda): rewrite README in the house style
Match the ja3-ja4 / zingela README convention: ANSI Shadow banner, badge row (Project 37, Go, keyless, single static binary, AGPL), blockquote pitch, then Why / What Works Today / Quick Start with real sample output / just TIP / Learn table / Architecture diagram / Build and Test / Project Structure. Drops the phantom just-watch reference (no such recipe). Content tracks the verified code: news-first 70/30 weights, Log4Shell KAT as CWE-502.
2026-07-09 12:17:59 -04:00
Carter Perez bcd9aef757
Merge pull request #302 from CarterPerez-dev/dependabot/npm_and_yarn/PROJECTS/advanced/rveng/frontend/axios-1.16.0
chore(deps): bump axios from 1.13.2 to 1.16.0 in /PROJECTS/advanced/rveng/frontend
2026-07-09 08:18:55 -04:00
CarterPerez-dev 679a86d593 docs(nadezhda): fix learn/ weight-split and Log4Shell CWE
The 70% news bloc is recency+velocity+source+keyword, not recency+velocity alone (which sum to 0.50). Log4Shell surfaces as CWE-502 (first CNA problemType, per TestCVEListParsesLog4Shell), not CWE-20. Also reword the 04-CHALLENGES weight aside to match.
2026-07-09 07:19:31 -04:00
CarterPerez-dev 5ece03699b docs(nadezhda): M8 learn/ folder
Five teaching docs (overview, concepts, architecture, implementation, challenges) grounded in real incidents (Log4Shell CVE-2021-44228, Citrix Bleed 2 CVE-2025-5777, Equifax CVE-2017-5638, MOVEit CVE-2023-34362). ASCII pipeline + data-model diagrams, a code walkthrough by function name (no line numbers), and challenges from adding a source to replacing clustering with LSH. No em dashes, per the repo's docs style.
2026-07-07 02:37:39 -04:00
CarterPerez-dev a27cae6ab7 build(nadezhda): M8 release packaging - install.sh, goreleaser, CI, LICENSE
One-shot install.sh (curl|bash -> prebuilt release binary, or go install fallback with Go-toolchain bootstrap; installs to ~/.local/bin and wires PATH). .goreleaser.yaml + .github/workflows/release.yml build cross-platform binaries on a v* tag (inert in the monorepo, active once the project dir is the standalone repo root).

Add the AGPL-3.0 LICENSE and rewrite README.md with install + quickstart. Make internal/version.Version a var so goreleaser injects the real version via ldflags. justfile gains watch (run daemon from source) and publish (drift-free rsync mirror to the standalone github.com/CarterPerez-dev/nadezhda checkout).
2026-07-06 22:56:00 -04:00
CarterPerez-dev f65d197c96 feat(nadezhda): M7 watch daemon with optional webhook notify
Add a watch command (--interval, --once, --no-enrich): a long-lived daemon that re-ingests every enabled source on a ticker and, when a webhook is configured, POSTs genuinely new high-signal stories to it (Slack, Discord, or any JSON endpoint via a text/content/items payload).

internal/watch is a pure, stdlib-only scheduler: the pipeline is injected as a Cycle closure, so the daemon is fully unit-testable with a fake ticker and notifier. Graceful shutdown on SIGINT/SIGTERM returns cleanly; a cycle error is logged and the loop continues (fail-soft).

Notify uses a dedicated fetch-time watermark (store.NewlyFetchedClusters) so a freshly ingested but older-dated advisory is surfaced, which a publish-time filter would drop. Notable stories are capped by watch.notify_max_items and filtered by score threshold or KEV status.

Extract the shared ingest and cluster sequence (pipeline.go) so scrape and watch cannot drift, and route scrape and enrich through cmd.Context() so they honor SIGTERM too.
2026-07-06 22:07:31 -04:00
CarterPerez-dev d57bcc15b6 feat(nadezhda): M6 AI ideation layer (ideate + TUI i-key)
Add an opt-in ideation layer that turns ranked story clusters into content angles. A Provider interface backs four models: qwen (default, local Ollama), OpenAI, and Gemini share one OpenAI-compatible client; an Anthropic Messages client is written against raw net/http (no vendor SDK, uniform + dep-light). Results persist in ai_notes with a UNIQUE(cluster_id, provider) index (migration 0003), so re-ideation upserts in place.

The ideate command skips any (cluster, provider) that already has a note unless --force is passed; benign classifier refusals get their own counter and never fail the run. In the TUI, i ideates the selected cluster inline and renders an AI IDEAS section in the dossier; it is a no-op unless AI is enabled and only acts in the detail view.
2026-07-06 21:26:52 -04:00
CarterPerez-dev 0a86bb8593 feat(nadezhda): AI setup wizard (nadezhda ai) + credential store + Ollama port fix
Add a re-runnable interactive wizard that configures an AI provider for the ideation layer: Claude, OpenAI, Gemini, or a local Ollama. Keys persist to ~/.config/nadezhda/credentials (0600, atomic temp+rename) and auto-load on every run; a shell-exported key always wins over the file. A key-name allowlist (NADEZHDA_* / *_API_KEY) blocks env-name injection into spawned subprocesses.

The Ollama path detects a running instance and auto-configures it, else writes an embedded compose file plus one docker command, else prints an install hint. Ollama's host port is remapped to a non-default 39847 (OLLAMA_HOST_PORT) to avoid colliding with an existing Ollama on 11434; the container-internal port stays 11434.

Thread a signal-cancellable root context through cobra (ExecuteContext). Default the Anthropic model to claude-sonnet-4-6.
2026-07-06 21:26:10 -04:00
Carter Perez d2b7e4758a
Enhance README with ASCII art and badges
Added ASCII art and updated project badges in README.md
2026-07-06 10:27:51 -04:00