Skip to content
This repository was archived by the owner on Oct 24, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3142b73
ops: GitHub organization configuration runbook, settings scripts, gro…
PetrefiedThunder Oct 19, 2026
3ad1a97
docs(org): record branch-cleanup dry run counts and that the Actions …
PetrefiedThunder Oct 19, 2026
4b5a6d7
Merge remote-tracking branch 'origin/main' into claude/epic-cori-blscqw
claude Oct 20, 2026
38e95fb
fix(lint): silence F811 on fixtures imported into test_demo_key_funnel
PetrefiedThunder Oct 20, 2026
bd3de94
docs(org): the Actions block recurs in windows; point at the run banner
PetrefiedThunder Oct 20, 2026
64f6ae9
docs(org): record that the repositories went public on 2026-10-20
PetrefiedThunder Oct 20, 2026
f8984a3
Merge remote-tracking branch 'origin/main' into claude/epic-cori-blscqw
claude Oct 20, 2026
101d8f1
test: take main's F811 fix for test_demo_key_funnel (#837) over the p…
PetrefiedThunder Oct 20, 2026
a4e4453
fix(scripts): address Codex review on the GitHub settings and branch …
PetrefiedThunder Oct 20, 2026
5e0fd2f
docs(org): refresh branch-cleanup counts after the 2026-10-20 dry run
PetrefiedThunder Oct 20, 2026
b3da4b4
docs: point repository links at the agentmiddleware organization name…
PetrefiedThunder Oct 20, 2026
8bd6a3a
Merge remote-tracking branch 'origin/main' into claude/epic-cori-blscqw
claude Oct 20, 2026
109e593
Merge remote-tracking branch 'origin/main' into claude/epic-cori-blscqw
claude Oct 20, 2026
41af6f2
docs(org): record the history rewrite, relicense and their fallout
claude Oct 20, 2026
5c3aff0
Merge remote-tracking branch 'origin/main' into claude/epic-cori-blscqw
claude Oct 22, 2026
846536c
fix(ci): re-pin the secret-scan base after the history rewrite
claude Oct 22, 2026
fd1c42c
docs: runbook corrections from the 2026-10-22 fact-check
claude Oct 22, 2026
508c8f3
fix(db): release failed SQLite statements on the worker thread (Pytho…
claude Oct 22, 2026
e404e6d
docs: second round of fact-check corrections
claude Oct 22, 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: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security report
url: https://github.com/PetrefiedThunder/agent-middleware-api/security/advisories
url: https://github.com/agentmiddleware/agent-middleware-api/security/advisories
about: Report sensitive security vulnerabilities privately.
82 changes: 81 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,96 @@
version: 2

# Every Dependabot pull request runs the full CI matrix (about 75 billable
# Actions minutes per run on a private repository). Updates are therefore
# grouped: one pull request per ecosystem per interval instead of one per
# package. Six separate pip pull requests in one week (#783 to #788) cost
# roughly 450 minutes of a 2,000 minute monthly allowance.
#
# requirements.lock is produced by `make lock` (uv), not by Dependabot. The
# required lint job fails a pull request whose requirements.txt no longer
# matches the lock, and admins cannot bypass required checks, so a grouped
# pip update cannot merge until the lock is regenerated on its own branch:
# git fetch origin && git checkout <dependabot branch>
# make lock && git commit -am "build(deps): regenerate requirements.lock"
# git push
# Dependabot keeps that commit unless the branch is rebased.
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
day: "monday"
time: "06:00"
timezone: "America/Los_Angeles"
open-pull-requests-limit: 5
labels:
- dependencies
groups:
python-dependencies:
applies-to: version-updates
patterns:
- "*"
python-security:
applies-to: security-updates
patterns:
- "*"

# Published packages with their own manifests. Grouped per directory: at
# most one pull request each for the SDK and the four wrappers, instead of
# one per package. (A group spanning directories exists only as
# `group-by: dependency-name`, which is one pull request per dependency,
# worse for this purpose.)
- package-ecosystem: "pip"
directories:
- "/b2a_sdk"
- "/wrappers/*"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "America/Los_Angeles"
open-pull-requests-limit: 2
labels:
- dependencies
groups:
sdk-and-wrappers:
patterns:
- "*"
Comment thread
PetrefiedThunder marked this conversation as resolved.

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "America/Los_Angeles"
labels:
- dependencies
- ci
groups:
actions:
patterns:
- "*"

# Dockerfile and Dockerfile.dev pin python:3.12-slim by digest
# (tests/test_ci_supply_chain_pins.py requires the digest form). Dependabot
# keeps the digest form and moves it to the current image.
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "monthly"
labels:
- dependencies

# Railway infrastructure-as-code checked by scripts/trust_release_gate.sh
# (make check-railway-iac).
- package-ecosystem: "npm"
directory: "/.railway"
schedule:
interval: "monthly"
labels:
- dependencies
groups:
railway-iac:
patterns:
- "*"
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -606,9 +606,9 @@ jobs:

# Commit history of this push/PR: catches a secret that was added in one
# commit and deleted in a later one, which the working-tree scan misses.
# Only the new commits are scanned — older history was verified
# separately (see the scope note in .gitleaks.toml) and still contains
# the rotated 2026-08-06 key, so a full-history scan would always fail.
# Only the new commits are scanned; older history is covered by the
# full-history scans recorded in the scope note of .gitleaks.toml (most
# recently 2026-10-22, after the 2026-10-20 history rewrite).
- name: Scan commit range for committed secrets
env:
EVENT_NAME: ${{ github.event_name }}
Expand Down
40 changes: 27 additions & 13 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
# Secret-scanning config for CI.
#
# Scope note: CI scans the working tree plus the commits in each push/PR
# range (.github/workflows/ci.yml secret_scan). Older history was verified
# separately with a full-history `gitleaks detect --log-opts=--all` under this
# config, most recently on 2026-09-19. The only real credential ever committed
# is the 2026-08-06 leaked key (see docs/api-key-rotation.md), and it is
# reachable from main's own history — the 2026-08-24 note here previously
# claimed the flattening had removed it from main and that pruning stale
# branches would remove the reachable copies. Both were wrong: commit 9e45009
# is an ancestor of origin/main, and `git log origin/main -S` finds the value
# in three commits. The key was rotated dead at the provider on 2026-08-07,
# which was always the only real remediation, and the incident record
# deliberately publishes the retired value anyway. Do not restate the old
# claim. Every other historical finding is synthetic test material or a
# content hash, allowlisted below.
# range (.github/workflows/ci.yml secret_scan). Older history is covered by
# full-history scans (`gitleaks detect --log-opts=--all` under this config),
# most recently on 2026-10-22 against a fresh clone taken after the history
# rewrite of 2026-10-20: 1,410 commits across every branch, nothing outside
# the allowlist below. The only real credential ever committed is the key
# from the 2026-08-06 incident (committed 2026-08-04 in
# scripts/stress_test_live.py, removed from HEAD by #201 on 2026-08-07; see
# docs/api-key-rotation.md). It was rotated dead at
# the provider on 2026-08-07, which was always the only real remediation. It
# then stayed reachable from main's history (the 2026-08-24 note here claimed
# otherwise and was corrected on 2026-09-19) until the 2026-10-20 rewrite
# replaced its value with the literal ***REMOVED*** in every commit, so
# neither the value nor the commit that introduced it (formerly 9e45009) is
# reachable from any branch or tag any more. GitHub still serves that
# pre-rewrite commit by its full SHA until it is garbage-collected or purged
# by GitHub Support, and clones taken before 2026-10-20 still carry both (the
# repository has no forks as of 2026-10-22). Every other historical finding
# is synthetic test material, a content hash, or the ***REMOVED*** marker the
# rewrite left behind, all allowlisted below.

[extend]
useDefault = true
Expand Down Expand Up @@ -47,6 +53,9 @@ paths = [
# So do the framework wrappers' suites — same reason, different tree. Without
# this a full-history scan reports the wrappers' fake api_key= kwargs.
'''^wrappers/[^/]+/tests/''',
# The static site's Node test files mock the demo-key endpoint with
# synthetic keys, for the same reason as tests/ above.
'''^site/test_[^/]+\.(c|m)?js$''',
# Demo transcripts and copy-paste docs use placeholder keys.
'''^docs/demo-.*\.md$''',
# Research manifests map source paths to SHA-256 content hashes. The generic
Expand Down Expand Up @@ -95,4 +104,9 @@ regexes = [
# The public AWS KMS KeySpec enum value for Ed25519 keys (kms_signer.py); it
# names a key type, it is not key material.
'''^ECC_NIST_EDWARDS25519$''',
# The marker the 2026-10-20 history rewrite left in place of the retired
# 2026-08-06 key's value (scripts/stress_test_live.py at its 2026-08-04
# commit). It is not a credential; the key it replaced was rotated dead on
# 2026-08-07.
'''^\*\*\*REMOVED\*\*\*$''',
]
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ repos:
args: [--fix]
- id: ruff-format

# Local stand-in for GitHub push protection, which is not available on a
# private repository without the paid Secret Protection add-on. Scans the
# staged diff with the same .gitleaks.toml ruleset and the same gitleaks
# release as CI's secret_scan job, so a local pass predicts the CI verdict.
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.2
hooks:
- id: gitleaks

# mypy runs from the project environment (language: system) via `uv run`,
# matching how the Makefile invokes tools. The previous mirrors-mypy setup
# used an isolated env + the unbuildable `types-all` dep, which broke the
Expand Down
2 changes: 1 addition & 1 deletion FINAL_SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Per task requirements:

## Pull Request

**URL:** https://github.com/PetrefiedThunder/agent-middleware-api/pull/331
**URL:** https://github.com/agentmiddleware/agent-middleware-api/pull/331

**Title:** Verify quote-locked pricing vertical slice (already complete on main)

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# Agent Middleware API

[![CI](https://github.com/PetrefiedThunder/agent-middleware-api/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/PetrefiedThunder/agent-middleware-api/actions/workflows/ci.yml)
[![CI](https://github.com/agentmiddleware/agent-middleware-api/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/agentmiddleware/agent-middleware-api/actions/workflows/ci.yml)
![Version](https://img.shields.io/badge/version-v1.3.0--unreleased-lightgrey)
![Python](https://img.shields.io/badge/python-3.11%2B-blue)
![License](https://img.shields.io/badge/license-Apache%202.0%20(gateway%20is%20Fair%20Source%2C%20FSL--1.1)-blue)
Expand Down Expand Up @@ -97,7 +97,7 @@ Per-release detail: [CHANGELOG.md](CHANGELOG.md).
Prerequisites: Python 3.11+, [`uv`](https://docs.astral.sh/uv/), and `make`.

```bash
git clone https://github.com/PetrefiedThunder/agent-middleware-api.git
git clone https://github.com/agentmiddleware/agent-middleware-api.git
cd agent-middleware-api
make demo-ambiguous-retry
```
Expand Down
2 changes: 1 addition & 1 deletion TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,4 @@ SQLite-only tests will still pass; PostgreSQL-specific tests skip if unavailable
- Check [docs/PROOF_MATRIX.md](docs/PROOF_MATRIX.md) for what each proof command asserts (and what it does not).
- Review [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and `make` targets.

If you believe you've found a bug, use the [bug report template](https://github.com/PetrefiedThunder/agent-middleware-api/issues/new?template=bug_report.yml). For security issues, see [SECURITY.md](SECURITY.md).
If you believe you've found a bug, use the [bug report template](https://github.com/agentmiddleware/agent-middleware-api/issues/new?template=bug_report.yml). For security issues, see [SECURITY.md](SECURITY.md).
61 changes: 60 additions & 1 deletion app/db/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import logging
import os
import sqlite3
from contextlib import asynccontextmanager
from datetime import datetime
from typing import Any, AsyncGenerator
Expand Down Expand Up @@ -126,6 +127,59 @@ def _get_database_url() -> str | None:
return as_sqlalchemy_url(raw)


class _StatementReleasingCursor(sqlite3.Cursor):
"""Release a failed statement on the aiosqlite worker thread that ran it.

Through CPython 3.11, ``sqlite3.Cursor.execute``/``executemany`` leave the
prepared statement attached to the cursor when the step fails (unique
violation, "database is locked", ...); 3.12 resets and drops it in the
error path of the C-level query executor instead. A cursor that still owns
a statement resets it again when it is destroyed, and that sqlite3_reset()
call takes the connection mutex. The destruction happens wherever the
cyclic GC runs -- in practice the event-loop thread, since the failed
cursor survives in the traceback of the exception the caller handled --
while aiosqlite executes statements on a per-connection worker thread. If
that worker is inside sqlite3_step() waiting in SQLite's busy handler (it
holds the mutex for the whole wait), the event loop blocks until the busy
timeout expires; the writer being waited for can only commit from the
event loop, so the wait always runs to the full timeout. Under concurrent
governed MCP writes this surfaced as a 30 s stall plus "database is
locked", on the Python 3.11 CI leg only. Closing the cursor here, on the
worker thread that owns the connection, resets and detaches the statement
immediately, so its later destruction never enters SQLite. On 3.12+ the
close is a no-op for the statement and remains harmless.
"""

def execute(self, sql, parameters=(), /): # noqa: ANN001, ANN201
try:
return super().execute(sql, parameters)
except BaseException:
self._release_statement()
raise

def executemany(self, sql, seq_of_parameters, /): # noqa: ANN001, ANN201
try:
return super().executemany(sql, seq_of_parameters)
except BaseException:
self._release_statement()
raise

def _release_statement(self) -> None:
try:
self.close()
except Exception:
# The connection is already closed or otherwise unusable, so the
# statement cannot be reset; the original error is what matters.
pass


class _StatementReleasingConnection(sqlite3.Connection):
"""sqlite3 connection whose cursors are ``_StatementReleasingCursor``."""

def cursor(self, factory=_StatementReleasingCursor): # noqa: ANN001, ANN201
return super().cursor(factory)


def get_engine() -> AsyncEngine | None:
"""Get or create the async database engine.

Expand Down Expand Up @@ -153,7 +207,12 @@ def get_engine() -> AsyncEngine | None:
# choking on concurrent writes manifests as OperationalError
# "database is locked". connect_args + WAL mode below solve it
# for dev/test; production runs on PostgreSQL.
engine_kwargs["connect_args"] = {"timeout": 30}
engine_kwargs["connect_args"] = {
"timeout": 30,
# Releases a failed statement on the worker thread; see
# _StatementReleasingCursor (Python 3.11 event-loop stall).
"factory": _StatementReleasingConnection,
}
else:
engine_kwargs["pool_size"] = get_settings().DB_POOL_SIZE
engine_kwargs["max_overflow"] = get_settings().DB_MAX_OVERFLOW
Expand Down
2 changes: 1 addition & 1 deletion app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ async def periodic_cleanup():
contact=public_contact or None,
license_info={
"name": "Business Source License 1.1",
"url": "https://github.com/PetrefiedThunder/agent-middleware-api/blob/main/LICENSE",
"url": "https://github.com/agentmiddleware/agent-middleware-api/blob/main/LICENSE",
},
servers=[
{
Expand Down
4 changes: 2 additions & 2 deletions b2a_sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ python -m pip install -e './b2a_sdk[mcp]'
### Released artifact

The source in this checkout is `0.5.0`; the currently released artifact is
[`python-sdk-v0.4.0`](https://github.com/PetrefiedThunder/agent-middleware-api/releases/tag/python-sdk-v0.4.0).
[`python-sdk-v0.4.0`](https://github.com/agentmiddleware/agent-middleware-api/releases/tag/python-sdk-v0.4.0).
Download
[`b2a_sdk-0.4.0-py3-none-any.whl`](https://github.com/PetrefiedThunder/agent-middleware-api/releases/download/python-sdk-v0.4.0/b2a_sdk-0.4.0-py3-none-any.whl)
[`b2a_sdk-0.4.0-py3-none-any.whl`](https://github.com/agentmiddleware/agent-middleware-api/releases/download/python-sdk-v0.4.0/b2a_sdk-0.4.0-py3-none-any.whl)
and install that downloaded file:

```bash
Expand Down
2 changes: 1 addition & 1 deletion docs/GAP_CLOSURE_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class RateLimiter:
**Solution:** Audit and patch.

**Deliverables:**
- [ ] Review https://github.com/PetrefiedThunder/agent-middleware-api/security/dependabot
- [ ] Review https://github.com/agentmiddleware/agent-middleware-api/security/dependabot
- [ ] Update `requirements.txt` for critical + high severity
- [ ] Run full test suite post-update
- [ ] Document any breaking changes
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ consequential MCP tool behind a governed boundary. Start with the
| Confirm which commit production is actually running | [Deployment verification checklist](deployment-verification-checklist.md) |
| Plan a design-partner evaluation | [Design partner guide](../DESIGN_PARTNER_GUIDE.md) |
| Contribute to the repository | [Contributing guide](../CONTRIBUTING.md) |
| Configure the GitHub organization, branch protection, and Actions budget | [GitHub organization configuration](github-org-configuration.md) |

## Agent and API discovery

Expand Down
2 changes: 1 addition & 1 deletion docs/agentmarket-listing.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ IAM replacement, or broad agent-framework governance.
| Product | Replay-safe gateway debit + dispatch evidence + signed receipts |
| Mechanism | Permit → governed invoke → wallet charge → receipt → audit |
| Pricing | Controlled design-partner pilot; no public tier or SLA committed |
| Repo | https://github.com/PetrefiedThunder/agent-middleware-api |
| Repo | https://github.com/agentmiddleware/agent-middleware-api |

---

Expand Down
4 changes: 2 additions & 2 deletions docs/agentmarket-submission.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pilot.

## Repository

https://github.com/PetrefiedThunder/agent-middleware-api
https://github.com/agentmiddleware/agent-middleware-api

## Demo

Expand All @@ -100,7 +100,7 @@ agent-governance

## Contact

- GitHub Issues: https://github.com/PetrefiedThunder/agent-middleware-api/issues
- GitHub Issues: https://github.com/agentmiddleware/agent-middleware-api/issues
- Public operator email: intentionally omitted until a monitored address and
accountable identity pass the launch contact gate. Do not submit this listing
before those values are configured.
Loading
Loading