Commit Graph
6 Commits
Author SHA1 Message Date
Yogesh Ojha be75bde8b0 feat(api-keys): group providers by what each adds
Every provider carries a group: subdomain sources, lookups, exploit
intelligence, bug bounty platforms, out-of-band testing and chat. The
labels are one map in shared/definitions/api_keys.py with a mirror in
config/api-keys.ts, and the provider list returns the group and its
label. The Telegram provider and the shared notification bot are
mirrored on the frontend, and a grammar test pins all three mirrors.

Claude-Session: https://claude.ai/code/session_01RVAHQxZ7JAkoEiTCDiHYue
2026-09-27 10:00:33 +05:30
Yogesh OjhaandClaude Opus 5 0b853e04b6 chore: production-readiness review across the tree
A full static review of the 3.0 tree, run as two fan-out passes with every
finding verified against the running stack rather than taken on inspection.

Correctness and security
- instance settings encrypted the mask over the stored AI key: `!= MASK` never
  matched `••••••••abcd`, so saving settings destroyed the key and `test_ai`
  posted the mask as a bearer token
- the MFA token was replayable for its full five-minute life; the gate now
  checks revocation and consumes the token after a successful exchange
- logout revoked nothing for a bearer client while answering "Logged out"
- `POST /api-keys/{id}/test` returned the plaintext key inside httpx's error
  string, which embeds the whole URL
- an interest rule could be edited or deleted through another project's id
- redis ran the celery broker under `allkeys-lru`, free to evict a queued task
  or a chord counter; now `noeviction`
- nuclei's stored command carried the OAST token and every auth header
- a finalize step could poison the session and leave a scan RUNNING for ever
- `is:issue` raised TypeError on every search
- offset paging repeated and skipped rows in four dimensions
- a cancelled run kept a stale `scans.*_found` rollup
- every PDF report raised `KeyError: 'software'`
- `version_key` truncated a wide numeric run and inverted release ordering
- psycopg raises a NUL as a bare ValueError, above StatementError, so every
  savepoint guard was blind to the case it was written for

Performance
- endpoints.host had no trigram index: 35.9ms seq scan -> 0.389ms
- free text compiled to one OR, not the prescribed UNION ALL: 132ms -> 41ms
- `/http-assets/summary` and `/ips/summary` materialised whole tables
- the cross-link `ip` kind ran an estate query per page and drew nothing

Frontend
- `$effect` loaders that read the state they write, an unbounded request loop
  on a failing endpoint
- error states that rendered as empty states
- 2FA backup codes were unusable while the copy said they worked
- a "Scan history" dialog that always reported none
- ~400 duplicated lines across five filter bars, now one component

Build and tooling
- every scanner installed at @latest; all 13 pinned to the measured versions
- CI built `web/`, gone since 2.x, with tags that cannot be valid
- the prettier pre-commit hook discarded its filenames and always passed
- the test suite destroyed itself when run twice

Also: subdomains from public code, via a pinned github-subdomains source and a
GitHub API key that subfinder receives too; sublist3r and oneforall removed
after measuring one unique host in 89 across four targets.

Verified: 853 tests, ruff clean over eleven packages, svelte-check 0 errors,
the count-is-a-promise gate at 131 checks and 0 mismatches, and 143 GET routes
with no 5xx. Four migrations, each with an exercised downgrade.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DVkdx5ynZ6aof5kLFczmhX
2026-09-13 18:03:29 +05:30
Yogesh OjhaandClaude Fable 5.1 0a69f3201c copy: state the fact, delete the explanation
Repo-wide sweep of every user-facing string: frontend components, routes,
config and stores; API details and route docs; shared definitions and
models; stage config help; report prose; MCP, toolbox, interest and
connector text; notification and worker messages.

Descriptions that explained, reassured, justified or restated their title
are deleted. Confirm dialogs name what is removed and stop. Failed actions
read "<Noun> not <verbed>", successes "<Noun> <verbed>". No reader address,
no product-as-subject, no em-dashes or parentheticals in prose.

Mirrors updated on both sides: EPSS band help, compare refusal reasons,
interest labels. Four tests asserting on old wording follow the new text.
The rules are condensed into CLAUDE.md under Writing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SK5o8xR96cbSnAfjYSTPSe
2026-09-12 11:35:07 +05:30
Yogesh OjhaandClaude Opus 5 66c7501558 fix(ui): the interface obeyed none of the style rules the AI prompt enforces
reports/narrate/ai.py instructs the model: no marketing language, no hedging,
no filler, never an em dash, never a rhetorical question. The product broke all
three. There was a house style in this repository and it applied only to the
machine.

The activity feed printed Python dictionary keys. stage_count_summary rendered
key.replace('_', ' ') over StageResult.counts, so a live scan read "12 waf,
340 checked", "88 ptr", "412 http assets", "56 alive". _STAGE_COUNT_LABELS now
covers all 31 count keys with singular and plural, and an unlabelled key is
dropped rather than printed raw, so a new stage can never leak one again.

Errors had three registers: "Failed to X" (121), "Could not X" (28), and
"Couldn't X - try again" (6), alongside a passive form the result tables already
used. All of it is now "<Subject> could not be <verbed>", which names the thing
that failed before the failure. The rate limiter reads the key's TTL and says
how long to wait instead of "Please wait a moment".

Onboarding fired confetti and a party popper, opened with "Let's get your
instance set up", and asked an operator to tick "I've saved my backup codes".
confetti.ts is deleted.

Casing was split down the middle: the sidebar group read "Attack surface" while
the item under it read "Scheduled Scans", and page headings restated the nav in
Title Case. Sentence case throughout now, including SURFACE_LABELS, so the
backend and its mirror agree.

The KEV sentence in generated reports claimed a listing "means working exploit
code is public". It means exploitation has been observed in the wild. That one
printed under a client's letterhead.

Also: 18 "This action cannot be undone" in three spellings removed in favour of
the concrete consequence; every em dash, contraction and "Please" out of user
copy; surface vocabulary applied to alerts and the notification settings, not
only the result tables; the "X, not Y" antithesis thinned from ten uses to the
two that carry a real distinction; advice copy ("fix first", "worth a look",
"Add to renewal watchlist", which named a feature that does not exist) reduced
to the fact.

Nine rules are written up in the audit linked below and hold for new copy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LM9TbCGhGb4s6nag6PsuaT
2026-09-06 18:26:29 +05:30
Yogesh Ojha 69239333bc Refactor validation and DNS tools, implementation of onboarding wizard
- Added `clean_name` function to `validation.py` for name validation with max length.
- Simplified docstrings in `dnsx` client, parser, and service files for clarity.
- Enhanced error handling in `ViewDNSService` to prevent disabling keys on rate limits.
- Improved WHOIS service to handle concurrent inserts gracefully with integrity checks.
- Updated `Settings` class in worker config to inherit from `BaseAppSettings`.
- Added new dependencies in `pyproject.toml` for `apprise` and `cryptography`.
2026-06-21 21:56:20 +05:30
Yogesh Ojha 777d2ccf6f add viewdns 2026-02-09 14:14:26 +05:30