Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
8dc0809
Merge pull request #1 from vinaayakh-aot/feature/multiple-mcps
vinaayakh-aot Mar 31, 2026
93cb253
Updated Cerner and FHIR connection
vinaayakh-aot Mar 31, 2026
018ba62
cleanup and update mcp
vinaayakh-aot Mar 31, 2026
cc803d2
SDK connector added
vinaayakh-aot Apr 1, 2026
cab653b
Updated architecture
vinaayakh-aot Apr 1, 2026
2701380
Update Playground to work with the new architecture
vinaayakh-aot Apr 1, 2026
00e3fbd
Register full MCP tools for FHIR, Drive, SMTP
kesav-aot Apr 1, 2026
eabb762
Merge pull request #3 from kesav-aot/CNP-27-expose-all-actions-define…
vinaayakh-aot Apr 1, 2026
31feb45
Google drive connector has
vinaayakh-aot Apr 1, 2026
88de542
Updated Docs and UI
vinaayakh-aot Apr 1, 2026
4e0fa60
Merge pull request #4 from vinaayakh-aot/feature/ui-doc-updates
vinaayakh-aot Apr 1, 2026
77cdb13
Merge branch 'main' into feature/architecture-fix
vinaayakh-aot Apr 1, 2026
e5b8b56
Added Test coverage
vinaayakh-aot Apr 1, 2026
7302910
Add Documentation
vinaayakh-aot Apr 1, 2026
bc8dbbb
Updated Connector Class
vinaayakh-aot Apr 2, 2026
a225586
Fix inconsistency in MCP server responses
vinaayakh-aot Apr 2, 2026
8e10feb
Merge pull request #6 from vinaayakh-aot/feature/architecture-fix
vinaayakh-aot Apr 5, 2026
0e26561
Feature/python packages (#7)
vinaayakh-aot Apr 5, 2026
d678511
Feature/python packages (#8)
vinaayakh-aot Apr 6, 2026
7db3d8d
Fix missing SHA (#22)
vinaayakh-aot Apr 22, 2026
0d531cd
Add pluggable AuthProvider system (#10)
kesav-aot Apr 22, 2026
5fe5016
Redact SMTP email addresses in logs (#14)
kesav-aot Apr 22, 2026
a7175dd
Implemented MCP AuthN/AuthZ End-to-End (#19)
GokulVGAot Apr 23, 2026
330e89d
Implement native Streamable-HTTP transport support (#26)
kesav-aot Apr 23, 2026
42ff045
Add streamable-http agent transport and streaming (#30)
kesav-aot Apr 30, 2026
41e9a7d
mcp-auth-scenario-tested (#27)
GokulVGAot May 4, 2026
ab75ce9
Cnp 49 migrate stripe connector to node wire (#23)
rahul-aot May 5, 2026
7e50d5c
Add configurable timeouts, breakers, and sanitizers (#13)
kesav-aot May 5, 2026
470fc9e
CNP 47 migrate salesforce connector to node wire (#36)
rahul-aot May 6, 2026
2b8af07
Propagate HTTP headers and implement streamable agent chat support (#32)
kesav-aot May 6, 2026
ddc311b
feat(slack-connector): add Slack connector with messaging and file up…
kesav-aot May 7, 2026
5cfc5b4
Cnp 33 implement linting and type checkers (#12)
yaseen-aot May 7, 2026
03965d6
Enforce connector allowlist; resolve env vars in config (#15)
kesav-aot May 7, 2026
36c0991
Cnp 33 implement linting and type checkers (#39)
yaseen-aot May 7, 2026
64c60de
Add CI workflow for running pytest with coverage reports (#38)
rahul-aot May 7, 2026
bee4a4f
Refactor documentation and configuration for Node Wire platform (#42)
rahul-aot May 13, 2026
8457984
fhir identified issues - fixed (#28)
yaseen-aot May 13, 2026
15260d2
Cnp 43 identified issues in bindings (#18)
yaseen-aot May 13, 2026
9957ccc
Licensing & Copyright added (#31)
yaseen-aot May 13, 2026
65ecd72
Feature/merge prs (#44)
vinaayakh-aot May 14, 2026
4011bed
Enforce valid channel IDs for upload_file (#45)
kesav-aot May 14, 2026
a299a44
Add External Patient Viewer (read-only) (#43)
kesav-aot May 14, 2026
d89f913
fix(factory): skip unregistered connectors filtered by NW_ALLOWED_CON…
rahul-aot May 15, 2026
74177fe
Consolidate setup into README and add compliance docs (#50)
kesav-aot May 20, 2026
c1691a9
expose snake_case tool inputs while preserving Salesforce API aliases…
rahul-aot May 21, 2026
2fab698
Add Connector Apps view and streaming timers (#47)
kesav-aot May 21, 2026
babce8f
Add integration tests for Google Drive connector and enhance playgrou…
rahul-aot May 22, 2026
50817f8
Merge pull request #18 from rahul-aot/CNP-76-create-integration-tests…
rahul-aot May 22, 2026
0e49ba4
streamline environment variable retrieval for test recipient email
rahul-aot May 22, 2026
1780b7f
Merge pull request #19 from rahul-aot/CNP-76-create-integration-tests…
rahul-aot May 22, 2026
80ef687
Add Connector Apps card and navigation to Playground Home integration…
rahul-aot May 22, 2026
ba14342
Merge pull request #20 from rahul-aot/CNP-76-create-integration-tests…
rahul-aot May 22, 2026
2f05fb9
Add integration tests for Stripe connector in Playground
rahul-aot May 25, 2026
e8fb360
Refactor StripePage and test_stripe_integration for improved readability
rahul-aot May 25, 2026
f4ebbc7
Merge pull request #21 from rahul-aot/CNP-81-create-integration-tests…
rahul-aot May 25, 2026
34bc971
Add integration tests for Salesforce connector in Playground
rahul-aot May 26, 2026
4ec0c70
Merge branch 'main' into CNP-82-create-integration-tests-for-salesfor…
rahul-aot May 26, 2026
cd08cb8
Modify NW_ALLOWED_CONNECTORS in pytest workflow
rahul-aot May 26, 2026
5d76914
Refactor lead_email locator for improved readability
rahul-aot May 26, 2026
47b8ed6
Merge pull request #22 from rahul-aot/CNP-82-create-integration-tests…
rahul-aot May 26, 2026
e5a1e10
Add integration tests for Slack connector in Playground
rahul-aot May 26, 2026
d760199
Add integration tests for Slack and Salesforce connectors, update env…
rahul-aot May 26, 2026
71feab5
Remove unused import of random_email from Salesforce test helpers
rahul-aot May 26, 2026
e6ad94e
Refactor function signatures in Slack integration tests for improved …
rahul-aot May 26, 2026
1693c2a
Merge pull request #23 from rahul-aot/CNP-80-create-integration-tests…
rahul-aot May 26, 2026
5cb94c1
Add integration tests for Cerner and Epic FHIR connectors, and HTTP c…
rahul-aot May 28, 2026
1a5c563
Add Grafana telemetry and packaging notes
kesav-aot Jun 2, 2026
3d0af73
Update README.md
kesav-aot Jun 2, 2026
ac022c2
Update local-packages-to-images.md
kesav-aot Jun 2, 2026
c12f0bc
Add per-service build and NW_ALLOWED_CONNECTORS
kesav-aot Jun 4, 2026
0f43a86
Merge pull request #58 from kesav-aot/Readme-updation
sskrishnak Jun 4, 2026
b376a01
Merge pull request #57 from rahul-aot/CNP-75-create-integration-tests
sskrishnak Jun 4, 2026
5172152
Merge pull request #59 from kesav-aot/Docker-compose-issue-fix
sskrishnak Jun 4, 2026
b7b96b0
MCP authentication flag has inverted and updated
Jun 11, 2026
4cd5805
linitng issue resolved
Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .copyright.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SPDX-FileCopyrightText: 2026 AOT Technologies
SPDX-License-Identifier: Apache-2.0
43 changes: 43 additions & 0 deletions .github/workflows/docker-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
##
## SPDX-FileCopyrightText: 2026 AOT Technologies
## SPDX-License-Identifier: Apache-2.0
##

# Enforce baseline container hygiene: digest-pinned base image and non-root USER.
name: Docker policy

on:
push:
branches: [main, master]
paths:
- "Dockerfile"
- "docker/**"
pull_request:
paths:
- "Dockerfile"
- "docker/**"

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Verify Dockerfiles use digest-pinned FROM and non-root USER
shell: bash
run: |
set -euo pipefail
shopt -s nullglob
files=(Dockerfile docker/*/Dockerfile)
for f in "${files[@]}"; do
echo "Checking $f"
if ! grep -qE '^FROM [^[:space:]]+@sha256:[a-f0-9]{64}' "$f"; then
echo "ERROR: $f must use FROM image@sha256:<64-hex-digest>" >&2
exit 1
fi
if ! grep -qE '^USER[[:space:]]' "$f"; then
echo "ERROR: $f must end with a non-root USER directive" >&2
exit 1
fi
done
echo "PASS: all Dockerfiles pinned and non-root"
54 changes: 54 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
##
## SPDX-FileCopyrightText: 2026 AOT Technologies
## SPDX-License-Identifier: Apache-2.0
##


name: Lint and Type Check

on:
pull_request:
branches: [ "main" ]

jobs:
ruff:
name: Ruff Linters
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Run Ruff (Linting)
# --output-format=github automatically creates inline annotations on your PR code!
run: ruff check --output-format=github .

- name: Run Ruff (Formatting Check)
run: ruff format --check .

mypy:
name: Mypy Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Run Mypy (Type checking)
run: mypy
233 changes: 233 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
##
## SPDX-FileCopyrightText: 2026 AOT Technologies
## SPDX-License-Identifier: Apache-2.0
##

# Pinned action SHAs are immutable; update intentionally when upgrading.
# yamllint disable rule:line-length
name: Publish Node Wire package

# Manual trigger: go to Actions → "Publish Node Wire package" → Run workflow.
# package_path must match the allowlist below (prevents confused-deputy path abuse).
#
# Examples:
# package_path: packages/runtime
# package_path: packages/connectors/fhir_epic
# package_path: packages/connectors/google_drive
on:
workflow_dispatch:
inputs:
package_path:
description: |
Relative path to the package directory (must be allowlisted).
Examples: packages/runtime | packages/connectors/fhir_epic
required: true
type: string
version:
description: "Semver version to publish (e.g. 0.2.0)"
required: true
type: string

env:
PIP_AUDIT_VERSION: "2.7.3"
CYCLONEDX_BOM_VERSION: "4.6.1"

jobs:
# ─────────────────────────────────────────────────────────────────────────────
# Build a binary wheel for each platform (Linux / macOS / Windows).
# cibuildwheel compiles Cython extensions and produces manylinux / macosx /
# win_amd64 wheels. The NoPyBuild override in setup.py ensures .py source
# files are excluded from all wheels.
# ─────────────────────────────────────────────────────────────────────────────
build-wheels:
name: Build (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
permissions:
contents: read

steps:
- name: Validate package path (allowlist)
shell: python
run: |
import os
import sys

raw = "${{ inputs.package_path }}".strip().replace("\\", "/")
norm = os.path.normpath(raw).replace("\\", "/")
# Reject traversal / absolute paths
if norm.startswith("..") or os.path.isabs(raw):
print("ERROR: invalid package_path", file=sys.stderr)
sys.exit(1)
allowed = {
"packages/runtime",
"packages/connectors/http_generic",
"packages/connectors/stripe",
"packages/connectors/smtp",
"packages/connectors/google_drive",
"packages/connectors/fhir_cerner",
"packages/connectors/fhir_epic",
}
if norm not in allowed:
print(f"ERROR: package_path {norm!r} is not allowlisted.", file=sys.stderr)
print("Allowed:", sorted(allowed), file=sys.stderr)
sys.exit(1)
print(f"PASS: package_path {norm!r} is allowlisted")

- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Set up Python
uses: actions/setup-python@v5.3.0
with:
python-version: "3.11"

- name: Install build tools
run: python -m pip install --upgrade pip "cython>=3.0" "cibuildwheel>=2.16.0"

- name: Build platform wheel(s)
run: |
cd "${{ inputs.package_path }}"
python -m cibuildwheel --output-dir dist
env:
# Build only Python 3.11+ wheels (matches requires-python in pyproject.toml)
CIBW_BUILD: "cp311-* cp312-*"
# Skip 32-bit targets and PyPy — not supported
CIBW_SKIP: "*-win32 *-manylinux_i686 pp*"

# ── Security gate: verify no .py source files leaked into any wheel ──────
- name: Verify binary-only wheel (no .py source)
shell: python
run: |
import glob, sys, zipfile

wheels = glob.glob("${{ inputs.package_path }}/dist/*.whl")
if not wheels:
print("ERROR: No wheels produced", file=sys.stderr)
sys.exit(1)

leaked: dict[str, list[str]] = {}
for whl in wheels:
with zipfile.ZipFile(whl) as zf:
bad = [n for n in zf.namelist() if n.endswith(".py")]
if bad:
leaked[whl] = bad

if leaked:
print("SECURITY FAIL: .py files found in wheel(s):", file=sys.stderr)
for whl, files in leaked.items():
print(f" {whl}:", file=sys.stderr)
for f in files:
print(f" {f}", file=sys.stderr)
sys.exit(1)

print(f"PASS: {len(wheels)} wheel(s) verified — no .py source files")

- name: Record wheel SHA256 (artifact integrity)
shell: python
run: |
import glob, hashlib, pathlib, sys
dist = pathlib.Path("${{ inputs.package_path }}") / "dist"
wheels = sorted(dist.glob("*.whl"))
if not wheels:
print("ERROR: no wheels to hash", file=sys.stderr)
sys.exit(1)
lines = []
for w in wheels:
h = hashlib.sha256(w.read_bytes()).hexdigest()
line = f"{h} {w.name}"
print(line)
lines.append(line)
(dist / "sha256sums.txt").write_text("\n".join(lines) + "\n", encoding="utf-8")

- name: Upload wheel artifacts
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: wheels-${{ matrix.os }}
path: ${{ inputs.package_path }}/dist/*.whl
if-no-files-found: error

# ─────────────────────────────────────────────────────────────────────────────
# Collect all platform wheels, run supply-chain checks, publish to PyPI.
# Uses Trusted Publisher (OIDC) — no long-lived PyPI API tokens needed.
# Configure on PyPI: Settings → Publishing → Add Publisher (GitHub, this repo,
# workflow name = "Publish Node Wire package").
# ─────────────────────────────────────────────────────────────────────────────
publish:
name: Publish to PyPI
needs: build-wheels
runs-on: ubuntu-latest
permissions:
id-token: write # Required for Trusted Publisher OIDC
contents: read

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Set up Python
uses: actions/setup-python@v5.3.0
with:
python-version: "3.11"

- name: Download all wheel artifacts
uses: actions/download-artifact@v4
with:
path: dist-all

- name: Flatten into dist/ directory
run: |
mkdir -p dist
find dist-all -name "*.whl" -exec cp {} dist/ \;
echo "Wheels collected:"
ls dist/
sha256sum dist/*.whl | tee dist/sha256sums.txt

- name: Validate wheel version matches input
shell: python
run: |
import glob, sys

expected = "${{ inputs.version }}"
wheels = glob.glob("dist/*.whl")
if not wheels:
print("ERROR: No wheels found for publish", file=sys.stderr)
sys.exit(1)

bad = [w for w in wheels if f"-{expected}-" not in w and f"-{expected.replace('.', '_')}-" not in w]
if bad:
print(f"ERROR: Version mismatch. Expected {expected!r} in filename.", file=sys.stderr)
for w in bad:
print(f" {w}", file=sys.stderr)
sys.exit(1)

print(f"PASS: {len(wheels)} wheel(s) match version {expected!r}")

- name: Install built wheels for CVE scan
run: pip install dist/*.whl

- name: Vulnerability scan (CVE gate — blocks publish on HIGH or higher)
run: |
pip install "pip-audit==${{ env.PIP_AUDIT_VERSION }}"
pip-audit --fail-on HIGH

- name: Generate SBOM
run: |
pip install "cyclonedx-bom==${{ env.CYCLONEDX_BOM_VERSION }}"
cyclonedx-py environment -o sbom.json
echo "SBOM generated: sbom.json"

- name: Upload SBOM as release artifact
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: sbom-${{ inputs.version }}
path: sbom.json

- name: Publish to PyPI (Trusted Publisher / OIDC + Sigstore attestations)
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
with:
packages-dir: dist/
# attestations: true generates a Sigstore attestation automatically.
# Clients can verify with: pip download <pkg> && python -m pypi_attestation_viewer <whl>
attestations: true
Loading
Loading