mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-09-17 08:36:25 +00:00
fix(portals)!: reject unknown flags in all six CLIs
Silently discarded flags produced silently wrong results: jobdanmark with --query (its real flag is --text) returned all 13,862 jobs as if they matched, exit 0, empty stderr - indistinguishable from a real result set. The four bunli CLIs get an argv preflight built from each command's own options object; linkedin and freehire validate parsed flags against per-command known sets. help/version still pass, and add-portal.md's existing bogus-flag-exits-1 contract now holds for the reference implementations contributors copy. One linkedin pin updated: "--jobage-minutes -5" now fails as UNKNOWN_FLAG (the stray -5 token) rather than BAD_ARG - same loud-failure invariant, earlier gate. Review finding F13 (2026-08-19), decision approved by Mads. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
d4e0c64c3c
commit
3bfd525cc4
@@ -63,6 +63,16 @@ EXAMPLES
|
||||
Personal use only — uses LinkedIn's public pages; keep volume low (LinkedIn ToS).
|
||||
`
|
||||
|
||||
// Long-form flag names each command accepts (parseFlags resolves the short
|
||||
// aliases q/l/n to these before validation). "help"/"h" pass so `search --help`
|
||||
// still prints usage.
|
||||
const KNOWN_FLAGS: Record<string, Set<string>> = {
|
||||
search: new Set([
|
||||
"location", "query", "jobage", "jobage-minutes", "remote", "page", "limit", "format", "help", "h",
|
||||
]),
|
||||
detail: new Set(["format", "help", "h"]),
|
||||
}
|
||||
|
||||
async function main(): Promise<number> {
|
||||
const argv = process.argv.slice(2)
|
||||
const flags = parseFlags(argv)
|
||||
@@ -73,6 +83,25 @@ async function main(): Promise<number> {
|
||||
return cmd ? 0 : 1
|
||||
}
|
||||
|
||||
// Reject unknown flags instead of silently discarding them: a discarded
|
||||
// filter changes what the search returns with no error (a wrong flag name
|
||||
// once returned an entire portal's database as if it matched the query).
|
||||
// add-portal.md's contract requires a bogus flag to exit 1 with a JSON
|
||||
// error on stderr.
|
||||
const knownFlags = KNOWN_FLAGS[cmd]
|
||||
if (knownFlags) {
|
||||
for (const key of Object.keys(flags)) {
|
||||
if (key === "_" || knownFlags.has(key)) continue
|
||||
process.stderr.write(
|
||||
JSON.stringify({
|
||||
error: `unknown flag --${key} for '${cmd}' - flags are never silently ignored, because a discarded filter changes what the search returns; see --help for the supported flags`,
|
||||
code: "UNKNOWN_FLAG",
|
||||
}) + "\n",
|
||||
)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd === "search") {
|
||||
const location = typeof flags.location === "string" ? flags.location : undefined
|
||||
if (!location) {
|
||||
|
||||
Reference in New Issue
Block a user