Skip to content

Projects v2 board + publishable docker image + rename secscan→security-scan#6

Merged
nirmalgupta merged 5 commits into
mainfrom
feat/config-dir-and-skill
Jun 2, 2026
Merged

Projects v2 board + publishable docker image + rename secscan→security-scan#6
nirmalgupta merged 5 commits into
mainfrom
feat/config-dir-and-skill

Conversation

@nirmalgupta
Copy link
Copy Markdown
Member

@nirmalgupta nirmalgupta commented Jun 2, 2026

Summary

Three related changes that together make the scanner ready to be installed as a skill from leverj/ai-skills:

  1. Projects v2 board — drop the parent-epic / sub-issue model in favor of a flat Projects v2 board with Severity + Category single-select fields. Removes the 100-sub-issue cap that was blocking real runs. (Originally landed in PR Projects v2 board + Codex/Gemma SAST with cross-validation #5 / bd606f7.)
  2. Config in a directory + publishable docker image — move per-deployment config into a config/ directory (clean one-volume mount), build + publish the scanner as leverj/security-scan on Docker Hub, and bake a SECURITY-SCAN-MANIFEST.yaml into the image so consumer skills can do user-confirmed version upgrades with automated config migration.
  3. Rename secscansecurity-scan — cosmetic but pervasive. security-scan for user-facing names (CLI, project, image), security_scan for the Python module since identifiers can't have hyphens.

Branch contents (5 commits)

Commit What
18b6637 Config-as-directory + initial skill bundle (later removed).
1f50d07 SECURITY-SCAN-MANIFEST.yaml, Docker Hub publish workflow, pyproject 0.2.0.
ea8de06 Full rename secscansecurity-scan / security_scan. Marker regex accepts legacy secscan: markers for backward compat on existing project items.
345e902 CI workflow path fix (lint security_scan/, not the hyphenated form).
215b0e2 Final cleanup: SECSCAN_CONFIG_DIR env-var leak fixed; stale "sub-issue" docstrings rewritten; obsolete tools/backfill_markers.py removed; security-scan-spec.md rewritten as v2 for the new architecture; .claude/ added to .gitignore.

Test plan

  • 221 tests pass locally and in CI on the latest push.
  • ./security-scan.sh check green against the new config/ layout + renamed env vars.
  • docker build . succeeds and docker run --rm --entrypoint cat secscan:test /app/SECURITY-SCAN-MANIFEST.yaml returns the manifest verbatim.
  • CI: test job + docker-build job both green.
  • Post-merge: add DOCKERHUB_USERNAME + DOCKERHUB_TOKEN repo secrets, then git tag v0.2.0 && git push origin v0.2.0 to publish the first image to Docker Hub.

Companion work

The Claude Code skill that drives the image is on leverj/ai-skills branch feat/security-scan-skill. It pulls + runs leverj/security-scan:<pinned-tag>, checks Docker Hub for newer tags, and applies the manifest's declared config migrations on user confirmation.

🤖 Generated with Claude Code

…ctory

Two changes that go together:

1. Config files moved into a single config/ directory so the host-side bind
   mount is one volume instead of a per-file mount. This makes packaging the
   scanner as a Claude Code skill clean — every per-deployment file (main
   config, 1Password env file) lives in one place that maps to /config inside
   the container.

   Moved (git tracked, history preserved via rename):
     config.example.yaml          -> config/config.example.yaml
     .env.1password.tpl.example   -> config/.env.1password.tpl.example
   And (gitignored, plain move):
     config.yaml                  -> config/config.yaml
     .env.1password.tpl           -> config/.env.1password.tpl

   .gitignore updated. secscan.sh now defaults to config/ as the config
   directory, accepts --config-dir as a new flag, mounts the directory at
   /config:ro inside the container, and resolves env_file relative to that
   dir. SECSCAN_CONFIG_DIR env var added for skill use ("scan project foo
   uses this config dir, project bar uses that one").

   Dockerfile unchanged — it already expected /config/config.yaml.

2. New `skill/` directory ships a Claude Code skill bundle:

     skill/SKILL.md                  agent instructions (frontmatter + body)
     skill/references/README.md      high-level reference
     skill/references/CONFIG.md      full config schema + 1Password walkthrough
     skill/references/RUN.md         runbook, flags, exit codes, recovery
     skill/install.sh                copies skill into ~/.claude/skills/secscan/

   The skill is small — it's just instructions pointing at $SECSCAN_HOME for
   the actual scanner. Users clone this repo once, export SECSCAN_HOME, run
   skill/install.sh once. Updates to the scanner don't require re-installing
   the skill.

   The skill's SKILL.md documents the hard rules (never --no-dry-run without
   confirmation, never expose secrets, project board is source of truth).

README updated with a "Claude Code skill" section and all config paths
adjusted. 221 tests pass; `./secscan.sh check` reports green against the
new layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 2, 2026 17:07
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reorganizes secscan’s per-deployment configuration into a dedicated config/ directory (so the wrapper bind-mounts a single volume) and adds a Claude Code skill bundle (skill/) that documents how an agent should install and operate secscan safely.

Changes:

  • Move config/templates under config/ and update docs + .gitignore accordingly.
  • Update secscan.sh to support --config-dir / SECSCAN_CONFIG_DIR and mount the whole config directory at /config.
  • Add skill/ bundle (SKILL.md + references + installer script) and document it in the root README.

Reviewed changes

Copilot reviewed 7 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
secscan.sh Adds config-directory semantics, new flag/env override, and directory bind-mounting.
README.md Updates setup instructions for config/ layout and documents the Claude Code skill.
.gitignore Updates ignored paths for the new config layout.
config/config.example.yaml Example config template under the new directory structure.
config/.env.1password.tpl.example 1Password env-file template under the new directory structure.
skill/SKILL.md Agent-facing instructions: triggers, run procedure, and safety rules.
skill/references/README.md High-level reference for what secscan is and how it behaves.
skill/references/CONFIG.md Config schema and secrets setup reference for the agent.
skill/references/RUN.md Runbook: flags, exit codes, troubleshooting, and reporting guidance.
skill/install.sh Installer to copy the skill bundle into the user’s Claude skills directory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread security-scan.sh Outdated
Comment on lines 215 to 217
local config_dir="${SECSCAN_CONFIG_DIR:-$DEFAULT_CONFIG_DIR}"
local config="${SECSCAN_CONFIG:-$config_dir/config.yaml}"
local extra_args=()
Comment thread security-scan.sh Outdated
Comment on lines 126 to 128
local config_dir="${SECSCAN_CONFIG_DIR:-$DEFAULT_CONFIG_DIR}"
local config="${SECSCAN_CONFIG:-$config_dir/config.yaml}"
local ok=1
Comment thread skill/SKILL.md Outdated
2. **Check config.** Run `$SECSCAN_HOME/secscan.sh check`. If it reports any
`✗`, walk the user through the fix using `references/CONFIG.md` as the
source of truth. Common failure modes:
- missing `config/config.yaml` → copy from `config.example.yaml`
Comment thread security-scan.sh
Comment on lines 327 to 330
exec docker run --rm \
-v "$config":/config/config.yaml:ro \
-v "$config_dir":/config:ro \
"${env_args[@]}" \
"$IMAGE" "${extra_args[@]+"${extra_args[@]}"}"
Comment thread security-scan.sh
Comment on lines 366 to 369
exec op run --env-file="$ef" -- docker run --rm \
-v "$config":/config/config.yaml:ro \
-v "$config_dir":/config:ro \
"${env_args[@]}" \
"$IMAGE" "${extra_args[@]+"${extra_args[@]}"}"
Shifts the skill packaging strategy: instead of bundling skill files in this
repo, this repo produces a published Docker image (`leverj/security-scan`)
that ships a SECSCAN-MANIFEST.yaml inside. The companion ai-skills repo
hosts the actual Claude Code skill, which drives the image and reads the
manifest to do informed upgrades.

What's in this commit:

- Drop `skill/` directory entirely — that was a wrong-repo prototype. The
  real skill lives in leverj/ai-skills.

- `SECSCAN-MANIFEST.yaml` at repo root (baked into image at
  /app/SECSCAN-MANIFEST.yaml). A consumer skill reads it with:

      docker run --rm --entrypoint cat \\
        leverj/security-scan:<tag> /app/SECSCAN-MANIFEST.yaml

  It declares the image version, config_schema_version, changelog,
  breaking_changes, and most importantly a typed list of:
    - config.new_fields      (skill ADDs these to user's config.yaml if absent)
    - config.renamed_fields  (skill renames in-place)
    - config.removed_fields  (skill strips with user confirmation)

  This is the contract that lets the consumer skill do "image updated;
  here's what changes; want to upgrade?" without baking version-specific
  migration code into the skill itself.

- `.github/workflows/publish.yml` — on a `v*` tag, builds amd64+arm64
  images and pushes leverj/security-scan:<tag> + :latest to Docker Hub.
  A guard step verifies pyproject.toml's version + SECSCAN-MANIFEST.yaml's
  version match the tag before publishing. Requires repo secrets
  DOCKERHUB_USERNAME + DOCKERHUB_TOKEN.

- Bump pyproject.toml version 0.1.0 -> 0.2.0 (matches manifest).

- README: replace the (now-removed) "Claude Code skill" section with a
  short pointer to leverj/ai-skills.

Local smoke test: docker build + `--entrypoint cat /app/SECSCAN-MANIFEST.yaml`
returns the manifest verbatim. 221 tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@nirmalgupta nirmalgupta changed the title Config-as-directory + Claude Code skill bundle Config-as-directory + publishable docker image with manifest Jun 2, 2026
nirmalgupta and others added 3 commits June 2, 2026 12:34
Cosmetic rename across the codebase, image, manifest, and config:

  Python module       secscan/      -> security_scan/  (underscore — Python identifier)
  PyPI name           secscan       -> security-scan
  CLI entry point     secscan       -> security-scan
  Wrapper script      secscan.sh    -> security-scan.sh
  Manifest filename   SECSCAN-…     -> SECURITY-SCAN-MANIFEST.yaml
  Spec filename       secscan-spec  -> security-scan-spec.md
  Env vars            SECSCAN_*     -> SECURITY_SCAN_*

All log/user-facing strings now read `security-scan:` (hyphen). Python
imports use `security_scan` (underscore) since identifiers can't contain
hyphens.

Fingerprint marker compatibility: new issues are filed with the
`security-scan:` marker; the parser also accepts legacy `secscan:`
markers so dedup against existing project items continues to work
without a one-time backfill.

Image name was already `leverj/security-scan` so no change there.

Validated:
  - 221 tests pass after marker regex update
  - `pip install -e .` produces the `security-scan` CLI
  - `./security-scan.sh check` reports green
  - `docker build` succeeds and manifest extraction returns the new file

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The rename sweep over-applied the hyphen form to ci.yml; the lint step
was pointed at security-scan/ which doesn't exist. The Python package
directory is security_scan/ (Python identifiers don't allow hyphens).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the loose ends from the rename + Projects v2 work:

- security-scan.sh: SECSCAN_CONFIG_DIR -> SECURITY_SCAN_CONFIG_DIR.
  The earlier rename regex required a word boundary and underscores are
  word characters, so compound env-var names (like SECSCAN_CONFIG_DIR)
  slipped through. Functional bug: users following the new naming
  convention would set SECURITY_SCAN_CONFIG_DIR and find it ignored.

- Update stale docstrings/comments that still described the parent-epic /
  sub-issue model:
    security_scan/__init__.py    module docstring + version bump 0.1.0 -> 0.2.0
    security_scan/sync.py        _labels_for docstring
    security_scan/notify.py      _default_digest docstring
    security_scan/runners/syft.py module docstring

- Remove obsolete tools/backfill_markers.py. Its premise (backfill
  fingerprint markers onto sub-issues filed by an even older tool) no
  longer applies — Projects v2 items carry markers directly, and the
  manifest-driven config migration is the path for future evolution.

- Rewrite security-scan-spec.md as v2:
    * Drop parent-epic / sub-issue model throughout in favor of the
      Projects v2 board.
    * Add the new scanners (trivy, trufflehog, syft, codex, gemma).
    * Add the cross-validation section.
    * Add the image-manifest contract section.
    * Add a build/release section documenting the Docker Hub publish flow.
    * v1 lineage preserved in §17.

- Untrack .claude/scheduled_tasks.lock and add .claude/ to .gitignore;
  it's per-checkout session state, not part of the repo.

Validated: 221 tests pass, ./security-scan.sh check is green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@nirmalgupta nirmalgupta changed the title Config-as-directory + publishable docker image with manifest Projects v2 board + publishable docker image + rename secscan→security-scan Jun 2, 2026
@nirmalgupta nirmalgupta merged commit 2ca6b72 into main Jun 2, 2026
2 checks passed
@nirmalgupta nirmalgupta deleted the feat/config-dir-and-skill branch June 2, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants