From a4658bccc70c5b75ca3ceda6d6b5007aad983527 Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Sun, 21 Jun 2026 00:55:33 -0400 Subject: [PATCH 1/4] fix(cli): correct command names (show/rotate/revoke/verify/export/audit/stats) and fix Windows UTF-8 encoding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 7 commands were registered with name='list' instead of their proper names, causing silent overwrites — only the last registered 'list' command worked - Add sys.stdout/stderr.reconfigure(encoding='utf-8') on Windows to prevent cp1252 encoding crashes with Rich library Unicode symbols --- src/apiauth/cli.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/apiauth/cli.py b/src/apiauth/cli.py index 759ee5c..72099a6 100644 --- a/src/apiauth/cli.py +++ b/src/apiauth/cli.py @@ -9,6 +9,14 @@ from rich.table import Table from typing import Any +# Ensure UTF-8 output on Windows consoles that default to cp1252 +if sys.platform == "win32": + try: + sys.stdout.reconfigure(encoding="utf-8") + sys.stderr.reconfigure(encoding="utf-8") + except Exception: + pass + from . import __version__ from .keygen import create_api_key_entry, create_jwt_entry, rotate_jwt, rotate_key from .keystore import Keystore @@ -176,7 +184,7 @@ def list_keys(ctx: click.Context, service: str | None, json_output: bool, show_e # ── show ────────────────────────────────────────────────────────────── -@cli.command(name="list") +@cli.command(name="show") @click.argument("key_id") @click.pass_context def show(ctx: click.Context, key_id: str) -> None: @@ -199,7 +207,7 @@ def show(ctx: click.Context, key_id: str) -> None: # ── rotate ──────────────────────────────────────────────────────────── -@cli.command(name="list") +@cli.command(name="rotate") @click.argument("key_id") @click.option("--expiry-days", "-e", type=int, default=None, help="New expiry in days") @click.pass_context @@ -230,7 +238,7 @@ def rotate(ctx: click.Context, key_id: str, expiry_days: int | None) -> None: # ── revoke ──────────────────────────────────────────────────────────── -@cli.command(name="list") +@cli.command(name="revoke") @click.argument("key_id") @click.pass_context def revoke(ctx: click.Context, key_id: str) -> None: @@ -249,7 +257,7 @@ def revoke(ctx: click.Context, key_id: str) -> None: # ── verify ──────────────────────────────────────────────────────────── -@cli.command(name="list") +@cli.command(name="verify") @click.argument("api_key") @click.option("--json-output", "-j", is_flag=True, help="Output as JSON") @click.pass_context @@ -347,7 +355,7 @@ def import_key( # ── export ──────────────────────────────────────────────────────────── -@cli.command(name="list") +@cli.command(name="export") @click.option("--format", "-f", "fmt", type=click.Choice(["env", "json", "dotenv", "github-actions"]), default="env") @click.option("--service", "-s", default=None, help="Filter by service") @click.pass_context @@ -432,7 +440,7 @@ def _export_github_actions(active: list[dict]) -> None: # ── audit ───────────────────────────────────────────────────────────── -@cli.command(name="list") +@cli.command(name="audit") @click.pass_context def audit(ctx: click.Context) -> None: """Audit keystore: find expired, expiring, and revoked keys.""" @@ -491,7 +499,7 @@ def audit(ctx: click.Context) -> None: # ── stats ───────────────────────────────────────────────────────────── -@cli.command(name="list") +@cli.command(name="stats") @click.pass_context def stats(ctx: click.Context) -> None: """Show keystore statistics.""" From cb52ec03f8cf05e9bd787d1e3bfde5451f404a55 Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Tue, 23 Jun 2026 02:38:16 -0400 Subject: [PATCH 2/4] docs: add AGENTS.md for agent discoverability --- .gitignore | 1 - AGENTS.md | 30 ++++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 AGENTS.md diff --git a/.gitignore b/.gitignore index 18afbeb..4013739 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,5 @@ Thumbs.db .ruff_cache/ # Local opencode config -AGENTS.md .agents/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..b703b8d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,30 @@ +# apiauth + +## Purpose +CLI tool for API key and JWT lifecycle management with encrypted local store — generate, store, verify, rotate, and revoke keys with an encrypted local keystore. + +## Build & Test Commands +- Install: `pip install -e .` or `pip install apiauth` +- Test: `pytest tests/` (or `python -m pytest tests/ -v --tb=short`) +- Lint: `ruff check src/ --target-version py310` +- Build: `pip wheel . --wheel-dir dist/` +- CLI check: `apiauth --version && apiauth --help` + +## Architecture +Key directories: +- `src/apiauth/` — Main package (CLI, keystore, crypto, commands) +- `tests/` — Test suite +- `.github/workflows/` — CI/CD (auto-code-review.yml, ci.yml, publish.yml) +- `dist/` — Built distributions + +## Conventions +- Language: Python 3.10+ +- Test framework: pytest +- CI: GitHub Actions (matrix: Python 3.10, 3.11, 3.12, 3.13) +- Linting: ruff (line-length 120, target py310) +- Formatting: ruff +- Package layout: src/ layout with setuptools +- Type checking: py.typed included +- Dependencies: click, cryptography, pyjwt, rich, python-dateutil +- CLI entry point: apiauth.cli:cli +- Master branch: master \ No newline at end of file From d12b42bb3138f949f2318305a3623712e5f57797 Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Tue, 23 Jun 2026 21:09:48 -0400 Subject: [PATCH 3/4] fix: add missing newline at EOF in dependabot.yml --- .github/dependabot.yml | Bin 271 -> 264 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index da6115bedfa394604598f5c92a2c1b2ef88bd9a0..028a26d5821f8941eb82b3e4b77ebc7b049beac2 100644 GIT binary patch delta 129 zcmeBY>R=KsOD!tS%+Iq@FybmLNJ%V7Ew-B2E5TflSuoL1Sd~iw2#S+4Qd3HEQmw!| n1%=GKlGLKI#2hPy^3>GqoXUysH5=Qp4YC?b)N(nKzlYqYCF_={gRr1g8)? z4n&5E^Q)U-;Inj5Y?ca_qazAj;WgK8X}U~jCVoL^5#RX%aZ=RXMN2PWjs3)OK{BPq dXeyo!qGBR%td{OSe`nUEJ&g1EQI$U`+} Date: Tue, 23 Jun 2026 23:30:25 -0400 Subject: [PATCH 4/4] improve: add dependabot config, security audit to CI, and temp file ignore --- .github/dependabot.yml | Bin 264 -> 1130 bytes .github/workflows/ci.yml | 14 ++++++++++++++ .gitignore | 4 ++++ 3 files changed, 18 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 028a26d5821f8941eb82b3e4b77ebc7b049beac2..866d7c8c3ed0327ef62be27ce146b22edaec8c24 100644 GIT binary patch literal 1130 zcmc&zK~BRk5WM#ltM)>X3>An2xgjCJkuSK;CNXtlvtAd%>)F&zT16ay3pq|^c4ju4 z6+B|VuGCx4V0>5EI+14UJE%N?PV8IFSVDQAVP|?sp%f@C_DE5P1>7u-P_Y15!AsAL z=qH862p6Fb~xI^jgNg~YztTh8$HZ~cb?J7o&rp?VfAXb-^A9P1b-_hXR?AP q%g<>G4`%plqCnptc5S&yTctBCJOAg6-~Q^xzf1pwXR5c1LybN3n03-k$cK`qY diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b50fba8..cdd947a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,7 @@ on: permissions: contents: read + security-events: write jobs: test: @@ -37,6 +38,19 @@ jobs: - name: Run tests run: python -m pytest tests/ -v --tb=short + - name: Security audit (pip-audit) + run: | + pip install pip-audit + pip-audit -r <(pip freeze) --format json --output pip-audit.json || true + continue-on-error: true + + - name: Upload security audit + uses: github/codeql-action/upload-sarif@v3 + if: always() + with: + sarif_file: pip-audit.json + category: pip-audit + - name: Check CLI works run: | apiauth --version diff --git a/.gitignore b/.gitignore index 4013739..50a062d 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ Thumbs.db # Local opencode config .agents/ +# Temp files +temp_*.txt +*.tmp +