From 9ee17c6c9caf2679264deb3eaf882c898ae46b32 Mon Sep 17 00:00:00 2001 From: Amin Date: Wed, 22 Jul 2026 00:32:08 +0300 Subject: [PATCH] fix: repair 0.1.1 launch --- .gitattributes | 10 +++++++ .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- CHANGELOG.md | 15 +++++++++- README.md | 11 +++++--- docs/release-notes-v0.1.1.md | 37 +++++++++++++++++++++++++ package-lock.json | 4 +-- package.json | 4 +-- scripts/verify-package.mjs | 40 ++++++++++++++++++++++++--- src/cli/bin.ts | 5 ++++ src/cli/index.ts | 8 ------ src/core/types.ts | 2 +- test/cli/cli.test.ts | 2 +- tsup.config.ts | 1 + 13 files changed, 117 insertions(+), 24 deletions(-) create mode 100644 .gitattributes create mode 100644 docs/release-notes-v0.1.1.md create mode 100644 src/cli/bin.ts diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..713e738 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +* text=auto eol=lf + +*.ico binary +*.jpg binary +*.jpeg binary +*.png binary +*.webp binary +*.woff binary +*.woff2 binary +*.pdf binary diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 4b17d0b..e949f22 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -11,7 +11,7 @@ body: id: version attributes: label: IssueSafe version - placeholder: 0.1.0 + placeholder: 0.1.1 validations: required: true - type: dropdown diff --git a/CHANGELOG.md b/CHANGELOG.md index 5584317..651cc0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to IssueSafe will be documented here. The project follows [S ## [Unreleased] +## [0.1.1] - 2026-07-22 + +### Fixed + +- Run the packed npm CLI through a dedicated executable entry so `.bin` symlinks work consistently on Linux, macOS, and Windows. +- Normalize repository text files to LF so Prettier produces the same result on Windows and Linux CI runners. + +### Changed + +- Expand packed-package verification to cover the public file set, CLI version, stdin sanitization, and invalid-usage exit codes. +- Refresh installation, CLI, demo, and release documentation for the published package. + ## [0.1.0] - 2026-07-21 ### Added @@ -15,5 +27,6 @@ All notable changes to IssueSafe will be documented here. The project follows [S - Responsive local-only React review application with per-finding and per-category decisions. - Safe Markdown fencing, synthetic scenarios, documentation, security policy, CI, and package verification. -[Unreleased]: https://github.com/aminhanifm/IssueSafe/compare/v0.1.0...HEAD +[Unreleased]: https://github.com/aminhanifm/IssueSafe/compare/v0.1.1...HEAD +[0.1.1]: https://github.com/aminhanifm/IssueSafe/compare/v0.1.0...v0.1.1 [0.1.0]: https://github.com/aminhanifm/IssueSafe/releases/tag/v0.1.0 diff --git a/README.md b/README.md index 07cfcdb..6ee6d23 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # IssueSafe [![CI](https://github.com/aminhanifm/IssueSafe/actions/workflows/ci.yml/badge.svg)](https://github.com/aminhanifm/IssueSafe/actions/workflows/ci.yml) +[![npm version](https://img.shields.io/npm/v/@aminhanifm/issuesafe.svg)](https://www.npmjs.com/package/@aminhanifm/issuesafe) [![MIT License](https://img.shields.io/badge/license-MIT-f4b95f.svg)](LICENSE) **[Try the interactive demo](https://aminhanifm.github.io/projects/IssueSafe/)** ยท [Security policy](SECURITY.md) @@ -21,17 +22,17 @@ IssueSafe occupies the useful middle. It finds a conservative set of common patt ## Install -IssueSafe requires Node.js 22 or newer. The package is prepared for npm but will remain unavailable until the owner publishes `v0.1.0`. +IssueSafe requires Node.js 22 or newer and is published on npm as [`@aminhanifm/issuesafe`](https://www.npmjs.com/package/@aminhanifm/issuesafe). ```bash npm install --global @aminhanifm/issuesafe issuesafe --version ``` -Run without a global install after publication: +Run without a global install: ```bash -npx @aminhanifm/issuesafe sanitize application.log +npx @aminhanifm/issuesafe --version ``` ## CLI @@ -46,6 +47,9 @@ issuesafe sanitize application.log --output application.safe.log # Standard input and versioned JSON cat application.log | issuesafe sanitize --stdin --format json +# Standard input to sanitized text +cat application.log | issuesafe sanitize --stdin + # Keep diagnostically useful IP addresses and emails issuesafe sanitize application.log --disable ip,email @@ -192,7 +196,6 @@ Focused issues and pull requests are welcome. Read [CONTRIBUTING.md](CONTRIBUTIN ## Roadmap -- Owner-reviewed `v0.1.0` npm release - Additional conservative vendor-specific token shapes backed by public documentation - Import/export of redaction decisions without original values - Expanded accessibility and cross-browser regression coverage diff --git a/docs/release-notes-v0.1.1.md b/docs/release-notes-v0.1.1.md new file mode 100644 index 0000000..790bc6a --- /dev/null +++ b/docs/release-notes-v0.1.1.md @@ -0,0 +1,37 @@ +# IssueSafe v0.1.1 + +IssueSafe 0.1.1 is a focused launch repair for the published CLI and public browser demo. + +## Fixed + +- Added a dedicated Node executable entry that always runs the CLI, fixing empty output from `issuesafe --version` when npm launches the command through a `.bin` symlink on Linux. +- Kept `createCli()` and `runCli()` importable without side effects for library consumers and tests. +- Normalized repository text files to LF so Prettier behaves consistently across Ubuntu and Windows GitHub Actions runners. + +## Demo and repository polish + +- Deployed the browser application at the canonical portfolio URL: . +- Kept the optional repository Pages URL as a redirect to the canonical demo. +- Updated installation and CLI documentation for the live npm package. + +## Install + +```bash +npm install --global @aminhanifm/issuesafe +issuesafe --version +``` + +Or run it without a global installation: + +```bash +npx @aminhanifm/issuesafe --version +``` + +## Verification + +- Cross-platform formatting, linting, strict TypeScript, unit, component, and browser tests. +- Production package and browser-demo builds. +- Packed npm consumer checks for the installed version, stdin sanitization, public files, and exit codes. +- Desktop and mobile checks of the deployed browser workflow. + +IssueSafe detects common sensitive patterns, not every possible secret. Review sanitized output before sharing it, and revoke or rotate credentials that may have been exposed. diff --git a/package-lock.json b/package-lock.json index b5fbbed..eabbf9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@aminhanifm/issuesafe", - "version": "0.1.0", + "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@aminhanifm/issuesafe", - "version": "0.1.0", + "version": "0.1.1", "license": "MIT", "dependencies": { "commander": "^14.0.0" diff --git a/package.json b/package.json index a809286..4de5234 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@aminhanifm/issuesafe", - "version": "0.1.0", + "version": "0.1.1", "description": "Sanitize developer logs and create shareable bug reports without uploading anything.", "type": "module", "license": "MIT", @@ -29,7 +29,7 @@ "access": "public" }, "bin": { - "issuesafe": "dist/cli/index.js" + "issuesafe": "dist/cli/bin.js" }, "exports": { ".": { diff --git a/scripts/verify-package.mjs b/scripts/verify-package.mjs index 9a05b71..4a4ef53 100644 --- a/scripts/verify-package.mjs +++ b/scripts/verify-package.mjs @@ -7,7 +7,7 @@ const root = resolve(import.meta.dirname, ".."); const temporaryDirectory = await mkdtemp(join(tmpdir(), "issuesafe-package-")); const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm"; -function run(command, args, options = {}) { +function runRaw(command, args, options = {}) { const windowsBatch = process.platform === "win32" && command.endsWith(".cmd"); const executable = windowsBatch ? (process.env.ComSpec ?? "cmd.exe") : command; const executableArguments = windowsBatch @@ -20,12 +20,16 @@ function run(command, args, options = {}) { .join(" "), ] : args; - const result = spawnSync(executable, executableArguments, { + return spawnSync(executable, executableArguments, { cwd: options.cwd ?? root, encoding: "utf8", input: options.input, env: { ...process.env, npm_config_cache: join(root, ".npm-cache") }, }); +} + +function run(command, args, options = {}) { + const result = runRaw(command, args, options); if (result.status !== 0) { throw new Error(result.stderr || result.stdout || `${command} failed`); } @@ -37,6 +41,24 @@ try { const details = JSON.parse(packOutput); const filename = details[0]?.filename; if (!filename) throw new Error("npm pack did not report a tarball filename"); + const packedFiles = (details[0]?.files ?? []).map((file) => file.path); + const unexpectedFiles = packedFiles.filter( + (file) => + file !== "CHANGELOG.md" && + file !== "LICENSE" && + file !== "README.md" && + file !== "SECURITY.md" && + file !== "package.json" && + !file.startsWith("dist/"), + ); + if (unexpectedFiles.length > 0) { + throw new Error(`unexpected public package files: ${unexpectedFiles.join(", ")}`); + } + for (const requiredFile of ["dist/cli/bin.js", "dist/cli/index.js", "dist/index.js"]) { + if (!packedFiles.includes(requiredFile)) { + throw new Error(`public package is missing ${requiredFile}`); + } + } const tarball = join(temporaryDirectory, filename); const installDirectory = join(temporaryDirectory, "consumer"); await mkdir(installDirectory); @@ -49,7 +71,7 @@ try { process.platform === "win32" ? "issuesafe.cmd" : "issuesafe", ); const version = run(bin, ["--version"], { cwd: installDirectory }).trim(); - if (version !== "0.1.0") throw new Error(`unexpected CLI version: ${version}`); + if (version !== "0.1.1") throw new Error(`unexpected CLI version: ${version}`); const sanitized = run(bin, ["sanitize", "--stdin"], { cwd: installDirectory, @@ -57,6 +79,14 @@ try { }); if (sanitized !== "owner=[EMAIL_1]\n") throw new Error("installed CLI did not sanitize stdin"); + const invalidUsage = runRaw(bin, ["sanitize"], { cwd: installDirectory }); + if (invalidUsage.status !== 2) { + throw new Error(`installed CLI returned ${invalidUsage.status} for invalid usage instead of 2`); + } + if (!invalidUsage.stderr.includes("provide an input file")) { + throw new Error("installed CLI did not explain invalid usage on stderr"); + } + const packageJson = JSON.parse( await readFile( join(installDirectory, "node_modules", "@aminhanifm", "issuesafe", "package.json"), @@ -66,7 +96,9 @@ try { if (packageJson.name !== "@aminhanifm/issuesafe") throw new Error("installed package name changed"); - console.log(`Verified ${filename}: install, bin, version, and stdin workflow passed.`); + console.log( + `Verified ${filename}: public files, installed bin, version, stdin, and exit codes passed.`, + ); } finally { await rm(temporaryDirectory, { recursive: true, force: true }); } diff --git a/src/cli/bin.ts b/src/cli/bin.ts new file mode 100644 index 0000000..805b09c --- /dev/null +++ b/src/cli/bin.ts @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +import { runCli } from "./index.js"; + +process.exitCode = await runCli(process.argv.slice(2)); diff --git a/src/cli/index.ts b/src/cli/index.ts index 057ce6c..7840b57 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -1,7 +1,4 @@ -#!/usr/bin/env node - import { readFile, writeFile } from "node:fs/promises"; -import { pathToFileURL } from "node:url"; import { Command, CommanderError, InvalidArgumentError, Option } from "commander"; import { FINDING_CATEGORIES, @@ -153,8 +150,3 @@ export async function runCli(argv: readonly string[], io: CliIo = defaultIo): Pr return 2; } } - -const invokedPath = process.argv[1]; -if (invokedPath && import.meta.url === pathToFileURL(invokedPath).href) { - process.exitCode = await runCli(process.argv.slice(2)); -} diff --git a/src/core/types.ts b/src/core/types.ts index e5adf96..84b845e 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -1,5 +1,5 @@ export const ISSUE_SAFE_SCHEMA_VERSION = "1.0" as const; -export const ISSUE_SAFE_VERSION = "0.1.0" as const; +export const ISSUE_SAFE_VERSION = "0.1.1" as const; export const FINDING_CATEGORIES = [ "private-key", diff --git a/test/cli/cli.test.ts b/test/cli/cli.test.ts index 14cfc66..46b3bac 100644 --- a/test/cli/cli.test.ts +++ b/test/cli/cli.test.ts @@ -115,7 +115,7 @@ describe("CLI", () => { const version = capture(); expect(await runCli(["--version"], version.io)).toBe(0); - expect(version.stdout.join("")).toBe("0.1.0\n"); + expect(version.stdout.join("")).toBe("0.1.1\n"); const sanitize = capture("clean"); expect(await runCli(["--no-color", "sanitize", "--stdin"], sanitize.io)).toBe(0); diff --git a/tsup.config.ts b/tsup.config.ts index aa07df6..7019533 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -4,6 +4,7 @@ export default defineConfig({ entry: { index: "src/index.ts", "cli/index": "src/cli/index.ts", + "cli/bin": "src/cli/bin.ts", }, format: ["esm"], target: "node22",