[Story] Git-ignore local secrets and environment files #19

Closed
opened 2026-08-26 19:31:46 +00:00 by kpcto · 10 comments
Owner

Intent

Add a .gitignore so local environment files and credentials (e.g. .env, .env.local, API tokens) can never be committed by accident. A one-file hygiene change to the repo.

Acceptance criteria

  • A .gitignore at the repo root ignores .env, .env.*, and node_modules
  • git check-ignore .env reports the file as ignored after the change
  • No currently tracked file is removed by the new ignore rules

Explicitly out of scope

  • No secret scanning, credential rotation, or backend changes
  • No changes to existing tracked files or their contents

Test plan

  • Run git check-ignore .env .env.local node_modules and confirm each path is reported ignored
  • Run the existing test suite (pnpm test) and confirm it stays green

Rollback note

  • Single commit adding one .gitignore file; revert the commit to remove, no migration

Owning stream

platform

Risk quadrant

agent-full

## Intent Add a `.gitignore` so local environment files and credentials (e.g. `.env`, `.env.local`, API tokens) can never be committed by accident. A one-file hygiene change to the repo. ## Acceptance criteria - A `.gitignore` at the repo root ignores `.env`, `.env.*`, and `node_modules` - `git check-ignore .env` reports the file as ignored after the change - No currently tracked file is removed by the new ignore rules ## Explicitly out of scope - No secret scanning, credential rotation, or backend changes - No changes to existing tracked files or their contents ## Test plan - Run `git check-ignore .env .env.local node_modules` and confirm each path is reported ignored - Run the existing test suite (`pnpm test`) and confirm it stays green ## Rollback note - Single commit adding one `.gitignore` file; revert the commit to remove, no migration ### Owning stream platform ### Risk quadrant agent-full
kpcto added the
kind
story
status
proposed
labels 2026-08-26 19:31:46 +00:00
kpcto added
status
ready
and removed
status
proposed
labels 2026-08-26 19:33:26 +00:00
bot-dispatcher added
loop
1
status
in-progress
and removed
status
ready
labels 2026-08-26 19:33:28 +00:00
Member
agent: dispatcher
phase: complete
plan_summary: Dispatch #19: [Story] Git-ignore local secrets and environment files (platform, security-gated)
```yaml agent: dispatcher phase: complete plan_summary: Dispatch #19: [Story] Git-ignore local secrets and environment files (platform, security-gated) ```
bot-dispatcher added the needs/security-reviewneeds/security-review labels 2026-08-26 19:33:29 +00:00
Member
agent: implementer
phase: start
plan_summary: >
  Implement #19: add root .gitignore ignoring .env, .env.*, and node_modules.
  Verify with git check-ignore and confirm no tracked files are affected.
  Single commit on feature/19, open PR to main, confirm CI green.
```yaml agent: implementer phase: start plan_summary: > Implement #19: add root .gitignore ignoring .env, .env.*, and node_modules. Verify with git check-ignore and confirm no tracked files are affected. Single commit on feature/19, open PR to main, confirm CI green. ```
Member
agent: implementer
phase: complete
plan_summary: >
  Done #19. PR #20 open (feature/19): single new root .gitignore ignoring
  .env, .env.*, and node_modules/. Verified git check-ignore .env/.env.local/
  node_modules all ignored; no tracked file affected (git ls-files clean, only
  A .gitignore staged). Test suite 53/53 pass locally; CI green: Run tests
  success, Secret scan (gitleaks) success. Criterion->test table in PR body.
pr: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/pulls/20"
status: ready-for-review
```yaml agent: implementer phase: complete plan_summary: > Done #19. PR #20 open (feature/19): single new root .gitignore ignoring .env, .env.*, and node_modules/. Verified git check-ignore .env/.env.local/ node_modules all ignored; no tracked file affected (git ls-files clean, only A .gitignore staged). Test suite 53/53 pass locally; CI green: Run tests success, Secret scan (gitleaks) success. Criterion->test table in PR body. pr: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/pulls/20" status: ready-for-review ```
Member
agent: tester
phase: start
plan_summary: >
  Probe PR #20 (feature/19) for #19 independently. Verify the root .gitignore
  ignores .env, .env.* and node_modules; confirm `git check-ignore .env`
  reports the file as ignored; confirm no currently-tracked file is removed.
  Report evidence with CI links on completion.
```yaml agent: tester phase: start plan_summary: > Probe PR #20 (feature/19) for #19 independently. Verify the root .gitignore ignores .env, .env.* and node_modules; confirm `git check-ignore .env` reports the file as ignored; confirm no currently-tracked file is removed. Report evidence with CI links on completion. ```
Member
agent: tester
phase: complete
verdict: pass
pr: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/pulls/20"
summary: >
  Independent probe of PR #20 (feature/19) for issue #19. Checked out the
  branch into a clean worktree and verified all three acceptance criteria
  directly. All pass.
checks:
  - criterion: "root .gitignore ignores .env, .env.*, and node_modules"
    result: pass
    evidence: >
      .gitignore at repo root (6 lines) contains `.env`, `.env.*`, and
      `node_modules/`. `git check-ignore -v .env .env.local .env.production
      .env.example` matches all four against .gitignore lines 5-6.
      `git check-ignore -v node_modules/` and `node_modules/<any path>` match
      line 2; `git status --short --ignored` lists `!! node_modules/`.
  - criterion: "`git check-ignore .env` reports the file as ignored"
    result: pass
    evidence: "`git check-ignore .env` prints `.env` and exits 0."
  - criterion: "no currently tracked file is removed"
    result: pass
    evidence: >
      main has 19 tracked files; feature/19 has 20, adding only `.gitignore`.
      `git ls-tree -r --name-only` diff shows zero deletions and no main-tracked
      path matches the new ignore rules. Working tree on the branch is clean.
ci:
  - name: "CI / Run tests (pull_request)"
    status: success
    url: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/actions/runs/29/jobs/0"
  - name: "CI / Secret scan (gitleaks) (pull_request)"
    status: success
    url: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/actions/runs/29/jobs/1"
notes: >
  Non-blocking nuance: `git check-ignore node_modules` with no trailing slash
  exits 1 because the `node_modules/` pattern only matches directories;
  `git check-ignore node_modules/` and any path under it exit 0, and real
  directory contents are correctly ignored (`!! node_modules/`). Acceptance is
  therefore met. Local `node --test` also confirms 53 passed / 0 failed.
```yaml agent: tester phase: complete verdict: pass pr: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/pulls/20" summary: > Independent probe of PR #20 (feature/19) for issue #19. Checked out the branch into a clean worktree and verified all three acceptance criteria directly. All pass. checks: - criterion: "root .gitignore ignores .env, .env.*, and node_modules" result: pass evidence: > .gitignore at repo root (6 lines) contains `.env`, `.env.*`, and `node_modules/`. `git check-ignore -v .env .env.local .env.production .env.example` matches all four against .gitignore lines 5-6. `git check-ignore -v node_modules/` and `node_modules/<any path>` match line 2; `git status --short --ignored` lists `!! node_modules/`. - criterion: "`git check-ignore .env` reports the file as ignored" result: pass evidence: "`git check-ignore .env` prints `.env` and exits 0." - criterion: "no currently tracked file is removed" result: pass evidence: > main has 19 tracked files; feature/19 has 20, adding only `.gitignore`. `git ls-tree -r --name-only` diff shows zero deletions and no main-tracked path matches the new ignore rules. Working tree on the branch is clean. ci: - name: "CI / Run tests (pull_request)" status: success url: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/actions/runs/29/jobs/0" - name: "CI / Secret scan (gitleaks) (pull_request)" status: success url: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/actions/runs/29/jobs/1" notes: > Non-blocking nuance: `git check-ignore node_modules` with no trailing slash exits 1 because the `node_modules/` pattern only matches directories; `git check-ignore node_modules/` and any path under it exit 0, and real directory contents are correctly ignored (`!! node_modules/`). Acceptance is therefore met. Local `node --test` also confirms 53 passed / 0 failed. ```
Member
agent: security
phase: started
subject:
  issue: 19
  pr: 20
  head_branch: feature/19
  base_branch: main
plan:
  - deterministic scans on the head tree (gitleaks for secrets, osv-scanner for dependencies, semgrep only if installed)
  - authz trace — expected n/a (no new routes/handlers; single config file)
  - input boundary / injection review of the changed file
  - verify diff stays within issue #19 scope (root .gitignore only)
status: review-in-progress
```yaml agent: security phase: started subject: issue: 19 pr: 20 head_branch: feature/19 base_branch: main plan: - deterministic scans on the head tree (gitleaks for secrets, osv-scanner for dependencies, semgrep only if installed) - authz trace — expected n/a (no new routes/handlers; single config file) - input boundary / injection review of the changed file - verify diff stays within issue #19 scope (root .gitignore only) status: review-in-progress ```
Member
agent: security
phase: completed
subject:
  issue: 19
  pr: 20
  head_branch: feature/19
  base_branch: main
  head_sha: e186faeb44f050320fa1af3a319aae6bf7c823a1
verdict: approve
summary: >
  Single new root .gitignore (6 lines, no tracked file touched). All three
  acceptance criteria of issue #19 independently re-verified on head_sha;
  deterministic scanners clean; no security surface added.
scans:
  gitleaks_tree:
    command: "gitleaks detect --source . --no-git --redact"
    result: clean — "no leaks found", exit 0
  gitleaks_history:
    command: "gitleaks detect --redact"
    result: clean — 30 commits scanned, "no leaks found"
  osv_scanner:
    command: "osv-scanner --recursive ."
    result: clean — package.json declares zero runtime deps, no lockfile present
  semgrep:
    result: skipped — binary not installed (playbook forbids installing);
      gap covered by manual input-boundary trace below
manual_review:
  authz_trace: n/a — diff adds no route, handler, or endpoint
  injection: none — .gitignore is static config consumed by git only;
    grep confirms no JS/HTML reads process.env/dotenv/.env at runtime
  unsafe_deserialization: n/a
  ssrf: n/a — no outbound requests introduced
acceptance_criteria:
  ac1_root_gitignore_ignores_env_and_node_modules: pass — "git check-ignore -v" matches .env at .gitignore:5, .env.local/.env.production at :6
  ac2_git_check_ignore_reports_dotenv: pass — prints ".env", exit 0
  ac3_no_tracked_file_removed_or_newly_ignored: pass — "git ls-files | git check-ignore --stdin" returns empty; status shows only new .gitignore
  test_suite_green: pass — "node --test" (= pnpm test script): 53 passed, 0 failed
scope_check:
  within_brief: true — diff contains exactly one added file (.gitignore), +6/-0
  pipeline_tripwire: clear — no changes to agents/, CI config, or .gitea/workflows/
severity_findings: []   # none at blocker/should level
nits:                   # informational, non-blocking
  - ".env.* also ignores a would-be tracked .env.example; add '!.env.example' later if an env template is ever wanted (trade-off already documented in the PR body)"
  - PR description cites "lines 4-6" for the pattern matches; actual match lines are 2, 5 and 6 (doc-only)
evidence_links:
  start_comment: https://git.stevanovic.co.uk/Fabrika/PersonalBlog/issues/19#issuecomment-408
  diff: https://git.stevanovic.co.uk/Fabrika/PersonalBlog/src/commit/e186faeb44f050320fa1af3a319aae6bf7c823a1/.gitignore
status: review-complete
```yaml agent: security phase: completed subject: issue: 19 pr: 20 head_branch: feature/19 base_branch: main head_sha: e186faeb44f050320fa1af3a319aae6bf7c823a1 verdict: approve summary: > Single new root .gitignore (6 lines, no tracked file touched). All three acceptance criteria of issue #19 independently re-verified on head_sha; deterministic scanners clean; no security surface added. scans: gitleaks_tree: command: "gitleaks detect --source . --no-git --redact" result: clean — "no leaks found", exit 0 gitleaks_history: command: "gitleaks detect --redact" result: clean — 30 commits scanned, "no leaks found" osv_scanner: command: "osv-scanner --recursive ." result: clean — package.json declares zero runtime deps, no lockfile present semgrep: result: skipped — binary not installed (playbook forbids installing); gap covered by manual input-boundary trace below manual_review: authz_trace: n/a — diff adds no route, handler, or endpoint injection: none — .gitignore is static config consumed by git only; grep confirms no JS/HTML reads process.env/dotenv/.env at runtime unsafe_deserialization: n/a ssrf: n/a — no outbound requests introduced acceptance_criteria: ac1_root_gitignore_ignores_env_and_node_modules: pass — "git check-ignore -v" matches .env at .gitignore:5, .env.local/.env.production at :6 ac2_git_check_ignore_reports_dotenv: pass — prints ".env", exit 0 ac3_no_tracked_file_removed_or_newly_ignored: pass — "git ls-files | git check-ignore --stdin" returns empty; status shows only new .gitignore test_suite_green: pass — "node --test" (= pnpm test script): 53 passed, 0 failed scope_check: within_brief: true — diff contains exactly one added file (.gitignore), +6/-0 pipeline_tripwire: clear — no changes to agents/, CI config, or .gitea/workflows/ severity_findings: [] # none at blocker/should level nits: # informational, non-blocking - ".env.* also ignores a would-be tracked .env.example; add '!.env.example' later if an env template is ever wanted (trade-off already documented in the PR body)" - PR description cites "lines 4-6" for the pattern matches; actual match lines are 2, 5 and 6 (doc-only) evidence_links: start_comment: https://git.stevanovic.co.uk/Fabrika/PersonalBlog/issues/19#issuecomment-408 diff: https://git.stevanovic.co.uk/Fabrika/PersonalBlog/src/commit/e186faeb44f050320fa1af3a319aae6bf7c823a1/.gitignore status: review-complete ```
bot-dispatcher removed the needs/security-reviewneeds/security-review labels 2026-08-26 21:21:45 +00:00
Member
agent: reviewer
verdict: approve
```yaml agent: reviewer verdict: approve ```
bot-dispatcher added
status
review
and removed
status
in-progress
kind
story
loop
1
labels 2026-08-26 21:23:49 +00:00
Member
agent: reviewer
verdict: approve
findings: []
```yaml agent: reviewer verdict: approve findings: [] ```
Member

Security approved; dispatching reviewer.

> Security approved; dispatching reviewer.
kpcto closed this issue 2026-08-26 21:37:40 +00:00
Sign in to join this conversation.