Skip to content

ci: initial GitHub Actions workflow (install + syntax + pytest collect)#14

Open
HaraldeRoessler wants to merge 1 commit into
MoltyCel:mainfrom
HaraldeRoessler:ci/initial-workflow
Open

ci: initial GitHub Actions workflow (install + syntax + pytest collect)#14
HaraldeRoessler wants to merge 1 commit into
MoltyCel:mainfrom
HaraldeRoessler:ci/initial-workflow

Conversation

@HaraldeRoessler
Copy link
Copy Markdown
Contributor

Summary

Adds initial GitHub Actions CI for moltrust-api. Three lightweight
jobs that catch the most common breakage modes without needing a
running API + database:

Job What it catches
install requirements dependency conflicts in requirements.txt (Python 3.12, matches the production Dockerfile)
syntax (python -m compileall) SyntaxError / IndentationError in any source dir before deploy
pytest --collect-only ImportError / fixture parse errors in test_*.py without booting the sandbox

Closes (in part) #9.

Validated

The workflow ran successfully on the fork branch first
(HaraldeRoessler#1, since closed) — all three jobs ✓.
Same workflow file is being merged unchanged.

Deliberately NOT included

  • Linting (ruff/flake8): existing code may have legacy style
    issues that would block this PR. Better added in a dedicated
    follow-up so the gate is one-thing-at-a-time.
  • Test execution: existing test_*.py target sandbox at
    localhost:8005 and need the API + Postgres + Web3 stack online.
    PR test: nonce manager unit tests, docker-compose, and smoke test #3 ships docker-compose.yml + scripts/smoke_test.sh which
    would slot in as a fourth job once merged. Keeping this PR small
    so it's easy to merge first.

Annotations you may see

GitHub will print two non-fatal warnings on every run:

  1. Node.js 20 actions are deprecatedactions/checkout@v4 and
    actions/setup-python@v5 will need a bump before
    September 2026. Easy follow-up.
  2. fatal: No url found for submodule path 'moltrust-openclaw' in .gitmodules during the Post Run cleanup of the checkout action.
    Pre-existing repo state — .gitmodules references
    moltrust-openclaw but the URL is missing. Out of scope for this
    PR; happy to clean that up separately.

Both are warnings on the Post Run, not job failures. Job exit codes
reflect only the actual work step.

🤖 Generated with Claude Code

First-cut CI for moltrust-api — three lightweight jobs that catch the
most-common breakage without needing a running API stack:

  install         pip install -r requirements.txt on Python 3.12
                  (matches Dockerfile). Flags dep conflicts.
  syntax          python -m compileall on every source dir.
                  Catches SyntaxError before deploy.
  pytest-collect  pytest --collect-only on root test_*.py files.
                  Catches test ImportError without booting sandbox.

Deliberately omitted (each is a follow-up of its own):

  - lint (ruff/flake8): existing code may have legacy style issues
    that would block this PR; better added in a dedicated PR.
  - test execution: existing tests target localhost:8005 and need
    the API + Postgres + Web3 stack online. PR MoltyCel#3 adds
    docker-compose.yml + scripts/smoke_test.sh which would slot in
    as a fourth job once merged.

Closes (in part) MoltyCel#9 "RFC: CI/CD pipeline and automated testing".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HaraldeRoessler added a commit to HaraldeRoessler/moltrust-api that referenced this pull request May 12, 2026
Follow-up to commit d25e70c (SSRF). After running CodeQL default-setup
on the fork, 17 additional findings surfaced. Triage outcome:

  Already closed by earlier commits this PR:   1 (SSRF)
  False positives (dismissed via CodeQL UI):   4
  Real findings fixed in this commit:          5
  Stack-trace-exposure (deferred to design):   7

FIXES IN THIS COMMIT

  #1 [LOG SANITISATION] credit_middleware exception swallows DB password
     - app/main.py (logger.error in credit_middleware)
     `logger.error("…: %s", caller_did, e)` — the raw exception `e`
     can be an asyncpg ConnectionError whose repr() includes the
     Postgres connection string (with the password). Log only
     `type(e).__name__` instead.

  MoltyCel#2 [DEFENSIVE URL ENCODING] /join?ref= referrer parameter
     - app/main.py /join handler
     The redirect target is HARDCODED to https://moltrust.ch — the
     host is not user-controlled. But `f"https://moltrust.ch?ref={ref}"`
     interpolates `ref` raw, and a payload like `ref="x&malparam=…"`
     could corrupt the query string. Use `urllib.parse.quote(ref)` to
     percent-encode the value before interpolation.

  MoltyCel#3 [STDOUT TOKEN LEAK] telegram_hn_remind print(r.text)
     - scripts/telegram_hn_remind.py
     `print(f'Status: {r.status_code}, Response: {r.text}')` — if
     Telegram error responses ever echo the request URL (which contains
     the bot token in the path), the body lands in stdout / CI scrollback.
     Print only the status code.

  MoltyCel#4 [ReDoS] mpp authorization header regex
     - packages/mpp/index.js
     `auth.match(/^(?:Payment|MPP)\s+(.+)$/i)` on an unbounded header
     is polynomial-quadratic. This package is published to npm, so
     consumer servers carry the risk. Cap header at 8 KiB and use
     bounded `\s{1,8}` with a non-greedy first char.

  MoltyCel#5 [ReDoS] moltrust-openclaw-v2 base URL trim
     - moltrust-openclaw-v2/src/client.ts
     `.replace(/\/+$/, "")` is polynomial on pathological inputs.
     Replace with a `while (str.endsWith("/")) str = str.slice(0, -1)`
     loop, which is linear.

DISMISSED AS FALSE POSITIVES (no code change)

  MoltyCel#14 py/clear-text-logging-sensitive-data at SPIFFE bind log
      Logs spiffe_uri, did, caller_did — none are passwords. CodeQL
      misfires on the "did" → "id" → "password" name-similarity heuristic.

  MoltyCel#13, MoltyCel#12 py/clear-text-logging-sensitive-data in scripts/threadwatch.py
      Telegram bot token flows into the request URL but never into a
      logger or print() call — only to requests.post (which doesn't
      log URLs by default).

  MoltyCel#16 py/weak-sensitive-data-hashing in _reg_tracker
      This is in-memory rate-limit bucket-key derivation, not password
      storage. bcrypt/argon2 would be wrong here (slow + salted breaks
      the lookup). SHA-256 of the full API key is the correct primitive
      for an O(1) tracker.

EXPLICITLY DEFERRED (7 stack-trace-exposure findings)

  Multiple endpoints currently return `{"error": str(e)[:100]}` to
  callers. CodeQL flags these as info disclosure. Fixing them means
  changing the API contract — clients that parse the `error` field
  would break. This is a design call for the maintainer; deferring
  to a separate PR + discussion rather than including in this hardening
  pass.

VERIFICATION

  Python 3.12 AST parse — app/main.py + scripts/telegram_hn_remind.py
  compile cleanly. `node -c packages/mpp/index.js` clean. The TS file
  change is a syntactically-trivial loop, not type-impacting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HaraldeRoessler added a commit to HaraldeRoessler/moltrust-api that referenced this pull request May 12, 2026
Lightweight workflow that runs on every push + PR to the fork.
Catches the common breakage modes from the security-hardening pass
without needing a running API or database:

  syntax       — `python -m compileall` on every source dir
  import-smoke — actually `from app.main import app` with all
                 required env vars set to placeholder values. This
                 catches startup-time RuntimeError raises that were
                 added by this PR (NONCE_SECRET, MOLTSTACK_DB_PW,
                 MOLTRUST_ADMIN_USERS) — they fail FAST here
                 instead of in production.
  pytest-coll  — `pytest --collect-only` over the in-repo tests.
                 Catches ImportError / SyntaxError in test modules.
  ruff         — informational lint, never blocks (continue-on-error)
  bandit       — informational SAST, never blocks (continue-on-error)

Separate filename (`fork-ci.yml`) from PR MoltyCel#14's proposed `ci.yml`
so the two can co-exist if PR MoltyCel#14 lands upstream later.

If reviewing this PR upstream and you prefer to land PR MoltyCel#14's
workflow first, this commit can be reverted independently —
none of the other security fixes in this PR depend on it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant