Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 31 additions & 0 deletions .github/workflows/package-contents.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Package contents

# The sdist once shipped an entire agent working directory because it had no
# include list and the build backend defaults to "everything not ignored".
# This fails the build if anything outside the package ever ships again.
on:
pull_request:
push:
branches: [master, main]

jobs:
sdist-scope:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install build
- name: Plant a stray directory the way an agent would
run: mkdir -p .claude/worktrees/probe && echo leak > .claude/worktrees/probe/leak.rs
- run: python -m build --sdist --outdir dist-check
- name: The sdist must contain only the package and its metadata
run: |
set -euo pipefail
tar tzf dist-check/*.tar.gz | sed 's|^[^/]*/||' | grep -v '^$' \
| awk -F/ '{print $1}' | sort -u > /tmp/top.txt
echo "top-level entries in the sdist:"; cat /tmp/top.txt
if grep -qE '^\.claude|^\.codex|^backend|^crates|^migrations' /tmp/top.txt; then
echo "::error::the sdist contains files from outside the package"; exit 1
fi
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,8 @@ dmypy.json
# OS
.DS_Store
Thumbs.db

# Agent working directories. These are not source and must never be packaged;
# an unscoped sdist published one to PyPI once already.
.claude/
.codex/
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,37 @@ All notable changes to the `oxarchive` Python SDK are documented here.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- **Webhooks**: `client.webhooks`, covering every route under `/v1/webhooks`
(endpoints, subscriptions, watched wallets, deliveries, the event-type
catalog, and the dry-run and estimate previews), each with an async twin.
- **Signature verification**: `WebhookVerifier`, plus the functional
`verify_webhook()`, `verify_webhook_signature()`, and
`parse_signature_header()`. Takes raw bytes, compares with
`hmac.compare_digest`, enforces a configurable replay window (5 minutes by
default), and accepts every `v1=` in the header so a delivery keeps
verifying through a 24-hour secret rotation overlap.
- New pydantic models exported at package root: `WebhookEndpoint`,
`WebhookSecret`, `WebhookSubscription`, `WebhookDelivery`,
`WebhookTestResult`, `WebhookRedelivery`, `WebhookWatchedAddress`,
`WebhookEventTypeDeclaration`, `WebhookDryRun`, `WebhookEstimate`, and the
preview value types (`WebhookWindow`, `WebhookOccurrence`,
`WebhookDayCount`, `WebhookLadderRung`, `WebhookDistribution`,
`WebhookEstimateBasis`).
- `HttpClient` gained PATCH and DELETE (`patch`/`apatch`, `delete`/`adelete`).
The webhook routes are the first in the API to need either.

### Notes
- Webhook delivery is a paid feature: Free plans hold no endpoints,
subscriptions, watched wallets, or deliveries. Free keeps `estimate()` and
`dry_run()`, so a rule can be designed and sized before upgrading. Per-plan
limits are in the README.
- Every webhook model allows unknown fields. Subscription pause state (set
when an account exceeds its deliveries-per-day allowance) passes through
untouched rather than being bound to field names that are still settling.

## [1.8.0] - 2026-07-27

### Added
Expand Down
Loading
Loading