Files
ai-job-search/.gitignore
T
Jakob Stender Guldberg 4c38f7ce4c fix(security): move the interview protection note to the rule that provides it (#337)
The two-line comment above `documents/interview/**` says interview prep and
experience records live there. Nothing has ever written to that directory:
/interview saves its pack to
documents/applications/<company>_<role>/interview_prep_<stage>.md, covered by
the documents/applications/** rule. `git grep documents/interview` returns
only the two declarations of the rule itself (.gitignore and
REQUIRED_IGNORE_RULES), `git log --all -- 'documents/interview*'` is empty,
and documents/README.md documents the applications path outright.

Nothing leaks - the comment is the defect, and it is the misleading kind. It
is the one dedicated, well-argued line about interview material in the
personal-data block, so an auditor checking that the framework's most
sensitive artifact is covered reads it and stops, at the only path in the
block with no writer.

The comment's description of what needs protecting was always right; only its
location was wrong. It now sits above documents/applications/**, the rule that
actually provides that protection, so a reader auditing the block finds the
reasoning attached to the rule doing the work. documents/interview/** stays -
REQUIRED_IGNORE_RULES pins it, so dropping it from .gitignore alone turns CI
red, and it is harmless defence in depth - relabelled in both files as
belt-and-braces rather than the primary guard.

The new check-ignore case in GitignorePatternBehaviorTests derives the
prep-pack path from /interview's own spec instead of hardcoding it. That
distinction is the whole value of the test: a hardcoded path pins only that
documents/applications/** still matches that shape, which security_guards.py
already catches first, and stays green if /interview moves its output -
leaving the corrected comment stale exactly the way this issue found it.
Since #329 the spec states the location in two pieces - Step 1 derives the
archive folder, Step 3 names interview_prep_<stage>.md - so the test pins both
fragments separately and composes the concrete path from them. Mutation-
verified on each half: repointing the folder at documents/prep_packs/, and
renaming the file, both fail this test while `python3 tools/security_guards.py`
still reports OK.

The class's temp-repo setup moved to setUp for the second case.

ayobamiseun reviewed the pre-rebase branch and called all three rebase hazards
in advance: the split literal, the released CHANGELOG context, and the setUp
re-merge. Reached independently here during the rebase; the review was posted
first.
2026-08-31 17:49:22 +02:00

119 lines
3.5 KiB
Plaintext

# Dependencies
node_modules/
bun.lock
# Python
__pycache__/
*.pyc
*.pyo
.venv/
venv/
# Compiled documents
*.pdf
*.aux
*.log
*.out
*.synctex.gz
*.fls
*.fdb_latexmk
# Personal data (never commit these)
salary_data.json
# Match at any depth: the job-scraper skill resolves `job_scraper/` relative to
# its own directory, so these land at .claude/skills/job-scraper/job_scraper/*.
# A rooted `job_scraper/...` pattern silently fails to match them.
**/job_scraper/seen_jobs.json
**/job_scraper/notion_sync.json
**/job_scraper/*.md
*_BehavioralReport.pdf
linkedin_Profile.pdf
# Secrets. A portal skill generated by /add-portal may need an API token for a
# fetching service; the .env holding it must never be committed.
.env
.env.*
# Personal photos and signatures
*.jpg
*.jpeg
*.png
!cover_letters/OpenFonts/fonts/**
# OS files
.DS_Store
Thumbs.db
# Editor
.vscode/
.idea/
# Memory files (Claude Code user-specific)
.claude/projects/
# Skills lock (auto-generated)
skills-lock.json
# Personal application output files (generated by /apply — do not share)
# Extension-agnostic on the ignore side: a custom template registered via
# /add-template (e.g. Typst) writes main_<company>_<role>.typ instead of
# .tex, and it must be ignored just as reliably as the stock LaTeX output.
# The negations stay .tex-only - the stock example files are always LaTeX,
# and a wildcard negation (!cv/main_example.*) would also re-include build
# artifacts like main_example.pdf/.aux.
cv/main_*.*
!cv/main_example.tex
cv/*.txt
cover_letters/cover_*.*
cover_letters/Cover_*.*
!cover_letters/cover_example.tex
# documents/ subfolder contents are personal — only README and folder structure are tracked
documents/cv/**
documents/linkedin/**
documents/diplomas/**
documents/references/**
# Also where /interview saves its prep packs (interview_prep_<stage>.md): these
# name the employers applied to, quote what was submitted, and set out the
# candidate's weak points.
documents/applications/**
documents/postings/**
# Belt-and-braces, not the primary guard: nothing writes here. Prep packs land
# in documents/applications/<company>_<role>/, covered above. Kept because
# tools/security_guards.py pins it in REQUIRED_IGNORE_RULES.
documents/interview/**
!documents/**/.gitkeep
# Personal job search tracking
job_search_tracker.csv
# Gmail sync state (message IDs, subjects - personal data)
gmail_sync/
# Generated reports (personal output from /html-report)
reports/
# Upskill reports (personal output). Depth-independent like the job_scraper
# rules above: the upskill skill resolves `upskill/` relative to its own
# directory, so a report can land at .claude/skills/upskill/upskill/*.md
# where the rooted rule cannot see it. `**/upskill/*.md` is not usable here -
# the skill directory shares the `upskill` name, so it would also ignore the
# skill's own SKILL.md - hence the report-file prefix is pinned instead.
upskill/*.md
**/upskill/report-*.md
# Company research cache (/apply Step 3, /interview Step 2 - personal search
# history). Referenced from commands, not a skill, so it resolves against the
# repo root normally - a plain rooted pattern is correct here, unlike the
# **/-prefixed job_scraper/upskill rules above.
company_research/*.json
# Agent skills: track the source, ignore only deps and logs.
# (A blanket `.agents/` ignore silently drops the job-search CLI skills from the repo.)
.agents/**/node_modules/
.agents/**/*.log
.agents/usage/
# Brainstorm mockups (superpowers visual companion) - never ship
.superpowers/