Single source of truth for the ai-bom monorepo, all SDKs, CI/CD, publishing, and conventions. Keep this file updated when things change. Last updated: 2026-02-18.
- Repo:
github.com/Trusera/ai-bom - License: Apache-2.0 (root + SDKs), MIT (n8n-node only)
- Branch protection: main requires 3 status checks (bypassed by admin PAT)
ai-bom/
├── src/ai_bom/ # Core scanner — PyPI: ai-bom
│ ├── scanners/ # 14 scanners
│ ├── reporters/ # 9 output formats
│ ├── compliance/ # OWASP + EU AI Act
│ ├── callable/ # Red-teaming bridge (Giskard)
│ ├── dashboard/ # FastAPI web dashboard
│ ├── cli.py # Typer CLI entrypoint
│ ├── policy.py # CI/CD policy enforcement
│ ├── server.py # FastAPI REST server
│ ├── watcher.py # Watchdog file watcher
│ └── __init__.py # __version__ lives here
├── trusera-agent-sdk/ # Python agent SDK — PyPI: trusera-sdk
├── trusera-sdk-js/ # TypeScript agent SDK — npm: trusera-sdk
├── trusera-sdk-go/ # Go agent SDK — go get
├── n8n-node/ # n8n community node — npm: n8n-nodes-trusera
├── vscode-extension/ # VS Code extension (VSIX)
├── templates/ # GitLab CI template
├── scripts/ # cedar-gate.py
├── examples/ # Example scan targets
├── tests/ # 651+ tests for ai-bom core
├── docs/ # MkDocs source
├── dist/ # GitHub Action dist (action.yml)
├── pyproject.toml # ai-bom package config
├── Makefile # Dev commands
├── Dockerfile # Docker distribution
└── .github/workflows/ # CI/CD (see below)
| Package | Directory | Registry | Current Version | Install |
|---|---|---|---|---|
| ai-bom | src/ai_bom/ |
PyPI | 3.3.2 | pip install ai-bom |
| trusera-sdk (Python) | trusera-agent-sdk/ |
PyPI | 1.0.0 (Stable) | pip install trusera-sdk |
| trusera-sdk (JS) | trusera-sdk-js/ |
npm | 0.2.0 (Beta) | npm install trusera-sdk |
| trusera-sdk-go | trusera-sdk-go/ |
Go modules | 0.1.0 (Beta) | go get github.com/Trusera/ai-bom/trusera-sdk-go |
| n8n-nodes-trusera | n8n-node/ |
npm | 0.5.0 | Install via n8n community nodes |
| ai-bom-scanner (VS Code) | vscode-extension/ |
VS Code Marketplace | 0.1.0 | Search "ai-bom" in Extensions |
| Package | Version source(s) |
|---|---|
| ai-bom | src/ai_bom/__init__.py → __version__ = "X.Y.Z" (hatch reads this) |
| trusera-sdk (Python) | trusera-agent-sdk/trusera_sdk/__init__.py + trusera-agent-sdk/pyproject.toml |
| trusera-sdk (JS) | trusera-sdk-js/package.json |
| trusera-sdk-go | No version file — version comes from git tag only |
| n8n-nodes-trusera | n8n-node/package.json |
| VS Code extension | vscode-extension/package.json |
Each package has its own tag prefix. The auto-release workflow uses these to track versions independently.
| Package | Tag format | Example |
|---|---|---|
| ai-bom | v* |
v3.3.2 |
| trusera-sdk (Python) | sdk-v* |
sdk-v1.0.0 |
| trusera-sdk (JS) | js-v* |
js-v0.2.0 |
| trusera-sdk-go | trusera-sdk-go/v* |
trusera-sdk-go/v0.1.0 |
| n8n-nodes-trusera | n8n-v* |
n8n-v0.5.0 |
| VS Code extension | vscode-v* |
vscode-v0.1.0 |
Runs on every push to main. Fully automated — no manual tagging needed.
- detect-changes job compares each directory against its latest tag
- Only packages with file changes get a release job
- Each job analyzes conventional commits touching that directory:
feat:→ minor bump (0.1.0 → 0.2.0)fix:→ patch bump (0.1.0 → 0.1.1)BREAKING CHANGEorfeat!:→ major bump (0.1.0 → 1.0.0)
- Skipped scopes (don't trigger releases):
feat(ci),feat(deps),feat(build),feat(chore)and same forfix(...) - Commits with
chore(release):prefix are ignored (prevents re-trigger loop) - Version files are updated, committed as
chore(release): <pkg> vX.Y.Z [skip ci], tagged, pushed - Package is built and published to the appropriate registry
| Package | Method | Auth |
|---|---|---|
| ai-bom | PyPI trusted publishing (OIDC) | No token needed (environment: pypi) |
| trusera-sdk (Python) | PyPI API token | PYPI_API_TOKEN secret |
| trusera-sdk (JS) | npm publish | NPM secret |
| trusera-sdk-go | Git tag only | GIT_TOKEN secret (for push) |
| n8n-nodes-trusera | npm publish | NPM secret |
Go to https://pypi.org/manage/project/<name>/settings/publishing/ and add:
- Owner:
Trusera, Repository:ai-bom, Workflow:auto-release.yml, Environment:pypi
Then remove the password: ${{ secrets.PYPI_API_TOKEN }} line for that package.
| Workflow | File | Trigger | Purpose |
|---|---|---|---|
| CI | ci.yml |
push/PR to main | Lint, typecheck, test (Python 3.10-3.13), security audit, SARIF upload |
| Auto Release | auto-release.yml |
push to main | Auto-version + publish all 5 packages |
| Publish to PyPI | publish.yml |
v* tags (manual) |
Standalone ai-bom PyPI publish (backup) |
| Publish Agent SDK | publish-sdk.yml |
sdk-v* tags (manual) |
Standalone agent SDK publish (backup) |
| Publish npm | publish-npm.yml |
n8n-v* tags (manual) |
Standalone n8n node publish (backup) |
| Publish VS Code | publish-vscode.yml |
vscode-v* tags |
VS Code marketplace publish |
| Docker | docker.yml |
v* tags |
Build + push Docker image |
| Docs | docs.yml |
push to main | Deploy MkDocs to GitHub Pages |
| Dogfood | dogfood.yml |
push to main | ai-bom scans itself |
| AI-BOM Example | ai-bom-example.yml |
push to main | Example scan via GitHub Action |
| Secret | Purpose | Used by |
|---|---|---|
GIT_TOKEN |
PAT with repo + workflow scope — bypasses branch protection for auto-release commits | auto-release.yml |
PYPI_API_TOKEN |
PyPI API token (user: trusera) — publishes trusera-sdk |
auto-release.yml, publish-sdk.yml |
NPM |
npm access token — publishes trusera-sdk and n8n-nodes-trusera | auto-release.yml, publish-npm.yml |
VSCE_PAT |
VS Code marketplace PAT | publish-vscode.yml |
| Scanner | File | What it detects |
|---|---|---|
| Code | code_scanner.py |
AI SDK imports, model references, API keys in source |
| Docker | docker_scanner.py |
AI frameworks in Dockerfiles |
| Network | network_scanner.py |
AI API endpoints in configs |
| Cloud (Terraform) | cloud_scanner.py |
AI services in IaC |
| n8n | n8n_scanner.py |
AI nodes, webhook auth, agent chains |
| Jupyter | jupyter_scanner.py |
AI usage in notebooks |
| GitHub Actions | github_actions_scanner.py |
AI integrations in workflows |
| MCP Config | mcp_config_scanner.py |
MCP server configs (claude, cline, cursor) |
| Model Files | model_file_scanner.py |
Binary models (.onnx, .pt, .safetensors, etc.) |
| AST (deep) | ast_scanner.py |
Python AST analysis (imports, decorators, calls) |
| AWS Live | aws_live_scanner.py |
Bedrock, SageMaker, Comprehend, Kendra |
| GCP Live | gcp_live_scanner.py |
Vertex AI, Dialogflow |
| Azure Live | azure_live_scanner.py |
Azure OpenAI, Cognitive Services, ML |
| Callable | callable/ |
Provider-agnostic model probing for red-teaming |
table, json (CycloneDX), sarif, spdx3, html, csv, junit, markdown, diff
| Module | File | Standard |
|---|---|---|
| OWASP LLM Top 10 | compliance/__init__.py |
LLM01-LLM10 mapping |
| OWASP Agentic Top 10 | compliance/owasp_agentic.py |
Agent-specific risks |
| EU AI Act | compliance/eu_ai_act.py |
Risk classification |
| License Compliance | compliance/licenses.py |
License checking |
ai-bom scan <path> # Basic scan
ai-bom scan <path> --deep # Enable AST scanner
ai-bom scan <path> -f sarif # Output format
ai-bom scan <path> --fail-on high # CI policy gate
ai-bom scan <path> --policy .ai-bom-policy.yml
ai-bom scan <path> --compliance owasp_llm_top10
ai-bom scan <path> --telemetry # Opt-in usage analytics
ai-bom scan <path> -q # Quiet mode for CI
ai-bom scan-cloud aws # Live cloud scanning
ai-bom dashboard # Launch web dashboardpip install ai-bom[dashboard] # FastAPI dashboard
pip install ai-bom[watch] # File watcher
pip install ai-bom[aws,gcp,azure] # Cloud live scanners
pip install ai-bom[callable-all] # All red-teaming providers
pip install ai-bom[all] # EverythingAll three SDKs share the same architecture: client, events, decorators/interceptor, Cedar policy, standalone mode.
from trusera_sdk import TruseraClient, monitor, Event, EventType
# Client with context manager
with TruseraClient(api_key="tsk_...") as client:
client.register_agent("my-agent", "langchain")
client.track(Event(type=EventType.TOOL_CALL, name="search", payload={...}))
# Decorator
@monitor(event_type=EventType.LLM_INVOKE)
def call_llm(prompt): ...
# Standalone (no API key needed)
from trusera_sdk import StandaloneInterceptor
with StandaloneInterceptor(policy_file="policy.cedar", enforcement="block"):
# HTTP requests are intercepted and policy-evaluated
...Modules: client.py, events.py, decorators.py, cedar.py, standalone.py
Integrations: LangChain (TruseraCallbackHandler), CrewAI (TruseraCrewCallback), AutoGen (TruseraAutoGenHook)
Build: hatchling (pyproject.toml, version in both __init__.py and pyproject.toml)
import { TruseraClient, EventType } from 'trusera-sdk';
const client = new TruseraClient({ apiKey: 'tsk_...' });
client.track({ type: EventType.TOOL_CALL, name: 'search', payload: {} });Modules: client.ts, events.ts, cedar.ts, interceptor.ts, standalone.ts
Interception: fetch (always), axios (optional), undici (optional) -- auto-detected at install-time
Integrations: LangChain.js (TruseraLangChainHandler with optional Cedar enforcement)
Build: tsup -- dual ESM (dist/index.js) + CJS (dist/index.cjs) with .d.ts declarations
Test: vitest
import trusera "github.com/Trusera/ai-bom/trusera-sdk-go"
client := trusera.NewClient("tsk_...")
client.RegisterAgent("my-agent", "custom")
client.Track(trusera.Event{Type: trusera.ToolCall, Name: "search"})Modules: trusera.go, events.go, cedar.go, interceptor.go, standalone.go
Build: standard Go modules (go.mod points to github.com/Trusera/ai-bom/trusera-sdk-go)
Test: go test ./... (CI gate in auto-release.yml runs tests before tagging)
Version: git tag only (trusera-sdk-go/vX.Y.Z), no version file
Env vars: TRUSERA_API_KEY (fallback for empty apiKey), TRUSERA_API_URL (fallback for base URL)
npm package: n8n-nodes-trusera
| Node | Purpose |
|---|---|
| TruseraScan | Run ai-bom scan on workflow JSON |
| TruseraDashboard | Interactive HTML dashboard with remediation cards |
| TruseraWebhook | Webhook trigger with direct HTML serving |
| TruseraPolicy | Policy enforcement gate |
| TruseraReport | Generate scan reports |
Build: tsc + copies SVG/PNG icons to dist
Test: jest
- Marketplace name:
ai-bom-scanner - VSIX:
ai-bom-scanner-0.1.0.vsix(47KB) - Publish:
vsce publish(needsVSCE_PAT) - Trigger:
vscode-v*tags viapublish-vscode.yml
push to main
├── CI (lint + typecheck + test on 3.10-3.13 + pip-audit + SARIF)
├── Dogfood (ai-bom scans itself)
├── AI-BOM Scan (example action)
├── CodeQL (security analysis)
└── Auto Release
├── detect-changes (which dirs changed?)
├── release-ai-bom (if src/ changed)
├── release-agent-sdk (if trusera-agent-sdk/ changed)
├── release-sdk-js (if trusera-sdk-js/ changed)
├── release-sdk-go (if trusera-sdk-go/ changed)
└── release-n8n-node (if n8n-node/ changed)
The repo itself is a GitHub Action. Users add it to their workflows:
- uses: trusera/ai-bom@v1
with:
path: .
format: sarif
fail-on: highThe action's dist/ directory contains the bundled scanner.
| Template | Location | Purpose |
|---|---|---|
| GitHub Action | action.yml + dist/ |
trusera/ai-bom@v1 |
| GitLab CI | templates/gitlab-ci-ai-bom.yml |
Include template for .gitlab-ci.yml |
- Python >= 3.10
- Node.js >= 18 (for JS SDK and n8n-node)
- Go >= 1.21 (for Go SDK)
pip install -e ".[dev]"
ruff check src/ tests/ # lint
ruff format src/ tests/ # format
mypy src/ai_bom/ # typecheck
pytest -v --cov=ai_bom # test (must pass 80% coverage)cd trusera-agent-sdk
pip install -e ".[dev]"
ruff check .
pytest -vcd trusera-sdk-js
npm ci
npm run build
npm testcd trusera-sdk-go
go test ./...cd n8n-node
npm ci
npm run build
npm testThe auto-release system depends on conventional commit messages. Always use:
feat: add new scanner for X → minor bump
feat(sdk): add retry logic → minor bump (if touching sdk dir)
fix: handle null response → patch bump
fix(n8n): correct webhook URL → patch bump (if touching n8n-node dir)
feat!: redesign API → major bump
chore: update deps → NO release
docs: update README → NO release
style: fix formatting → NO release
feat(ci): add new workflow → NO release (ci scope excluded)
feat(deps): bump dependency → NO release (deps scope excluded)
# 1. Bump version
sed -i 's/__version__ = ".*"/__version__ = "X.Y.Z"/' src/ai_bom/__init__.py
git add src/ai_bom/__init__.py
git commit -m "chore(release): ai-bom vX.Y.Z"
git tag vX.Y.Z
git push origin main --tags
# publish.yml triggers automatically on v* tag# 1. Bump both files
sed -i 's/__version__ = ".*"/__version__ = "X.Y.Z"/' trusera-agent-sdk/trusera_sdk/__init__.py
sed -i 's/^version = ".*"/version = "X.Y.Z"/' trusera-agent-sdk/pyproject.toml
git add trusera-agent-sdk/
git commit -m "chore(release): trusera-sdk vX.Y.Z"
git tag sdk-vX.Y.Z
git push origin main --tags
# publish-sdk.yml triggers on sdk-v* tagcd trusera-sdk-js && npm version X.Y.Z --no-git-tag-version && cd ..
git add trusera-sdk-js/package.json
git commit -m "chore(release): trusera-sdk-js vX.Y.Z"
git tag js-vX.Y.Z
git push origin main --tags
# Then manually: cd trusera-sdk-js && npm publish --access publicgit tag trusera-sdk-go/vX.Y.Z
git push origin trusera-sdk-go/vX.Y.Z
# Go proxy picks it up automaticallycd n8n-node && npm version X.Y.Z --no-git-tag-version && cd ..
git add n8n-node/package.json
git commit -m "chore(release): n8n-nodes-trusera vX.Y.Z"
git tag n8n-vX.Y.Z
git push origin main --tags
# publish-npm.yml triggers on n8n-v* taggit tag vscode-vX.Y.Z
git push origin vscode-vX.Y.Z
# publish-vscode.yml triggersThe trusted publisher on PyPI must list auto-release.yml as the workflow name. Go to PyPI project settings → Publishing → add it.
The GIT_TOKEN secret must be a PAT with repo scope that has admin/bypass permissions on the repo.
Check NPM secret is a valid token with publish access to both trusera-sdk and n8n-nodes-trusera.
A tag was created but the publish failed. Delete the orphaned tag, fix the issue, and re-tag.
The Go module proxy can take up to 30 minutes to index. Force it: GOPROXY=direct go get github.com/Trusera/ai-bom/trusera-sdk-go@vX.Y.Z
Race condition: the CI security job runs pip-audit before the new version appears on PyPI. This is expected for version bump commits and resolves on the next push.