{
  "markdown": "<!-- aicom-mirror-notice -->\n> **📖 Read-only mirror.** `aimarket-hub` is published from the canonical AI-Factory monorepo.\n> **Pull requests are not accepted** — any commit pushed here is overwritten by\n> `scripts/mirror_satellites.sh` on the next sync.\n> 🐞 Found a bug or have a request? Please **[open an issue](https://github.com/alexar76/aimarket-hub/issues)**.\n\n# AIMarket Hub\n\n<!-- aicom-readme-badges -->\n<p align=\"center\">\n  <a href=\"https://github.com/alexar76/aimarket-hub/actions/workflows/ci.yml\"><img src=\"https://raw.githubusercontent.com/alexar76/aimarket-hub/refs/heads/main/docs/badges/ci.svg\" alt=\"CI\" /></a>\n  <a href=\"https://github.com/alexar76/aimarket-hub/releases\"><img src=\"https://raw.githubusercontent.com/alexar76/aimarket-hub/refs/heads/main/docs/badges/release.svg\" alt=\"Release\" /></a>\n  <a href=\"https://github.com/alexar76/aimarket-protocol\"><img src=\"https://raw.githubusercontent.com/alexar76/aimarket-hub/refs/heads/main/docs/badges/aimarket.svg\" alt=\"Protocol\" /></a>\n  <a href=\"https://raw.githubusercontent.com/alexar76/aimarket-hub/refs/heads/main/docs/badges/coverage.svg\"><img src=\"https://raw.githubusercontent.com/alexar76/aimarket-hub/refs/heads/main/docs/badges/coverage.svg\" alt=\"Test coverage\" /></a>\n  <a href=\"https://github.com/alexar76/aimarket-hub/blob/main/LICENSE\"><img src=\"https://raw.githubusercontent.com/alexar76/aimarket-hub/refs/heads/main/docs/badges/license.svg\" alt=\"License: Apache-2.0\" /></a>\n</p>\n<!-- /aicom-readme-badges -->\n\n> 🌐 **English** · [Русский](docs/README.ru.md) · [Español](docs/README.es.md) · [Français](docs/README.fr.md) · [中文](docs/README.zh.md) · [Glossary](https://github.com/alexar76/aicom/blob/main/docs/localization-glossary.md)\n\n\n\n\n\n\n\n\n\n> **Ecosystem:** [AICOM overview & live demos](https://modeldev.modelmarket.dev) · **Package version:** `3.2.1` (pyproject) · **Community:** [Discord · Pollux](https://discord.gg/aimarket) · [Telegram · Castor](https://t.me/just_for_agents)\n\n**Federation hub for AI capability discovery, micropayment routing, and plugin-extensible invoke.**\n\nReference implementation of [AIMarket Protocol v2](https://github.com/alexar76/aimarket-protocol/blob/main/spec.md). One HTTP surface to **search** a federated catalog, **open payment channels**, **invoke** capabilities with safety and compliance hooks, and **settle** on-chain — without custodial wallets.\n\n| | |\n|---|---|\n| **Live hub** | [modelmarket.dev](https://modelmarket.dev) |\n| **Well-known** | [/.well-known/ai-market.json](https://modelmarket.dev/.well-known/ai-market.json) |\n| **Plugin demo** | [/plugins/demo](https://modelmarket.dev/plugins/demo) |\n| **Widget demo** | [/widget/demo](https://modelmarket.dev/widget/demo) |\n| **Plain-language value** | [docs/value.md](https://github.com/alexar76/aimarket-hub/blob/main/docs/value.md) |\n\n## Demo\n\n- **Live:** https://modelmarket.dev/\n- **Docs:** https://github.com/alexar76/aimarket-hub/blob/main/README.md\n\n---\n\n## Table of contents\n\n- [Overview](#overview)\n- [Architecture](#architecture)\n- [Repository layout](#repository-layout)\n- [Quick start](#quick-start)\n- [Core API](#core-api)\n- [Invoke lifecycle](#invoke-lifecycle)\n- [Plugin ecosystem](#plugin-ecosystem)\n- [Federation](#federation)\n- [Payments](#payments)\n- [Pay-on-Verified](#pay-on-verified)\n- [Configuration](#configuration)\n- [Deployment](#deployment)\n- [Development](#development)\n- [Security](#security)\n- [Related projects](#related-projects)\n- [License](#license)\n\n---\n\n## Overview\n\nAIMarket Hub sits between **capability providers** (factory-shipped products, [**oracles**](https://github.com/alexar76/oracles), peer hubs, data-cap publishers) and **consumers** (Flutter desktop apps, agents, embeddable widgets, MCP clients).\n\n**Problems it solves**\n\n| Problem | Hub answer |\n|---------|------------|\n| Fragmented AI APIs | Federated search over `.well-known/ai-market.json` peers |\n| Per-call payment friction | Pre-funded **channels** — one deposit, N micro-invokes, one settlement |\n| Trust in anonymous sellers | **Reputation** scores + stake bonds (plugin) |\n| Compliance & audit | **Provenance** receipts on every invoke (Ed25519 + W3C VC) |\n| Unsafe prompts | **Safety** pre-check with signed rejection + refund |\n\n\n### Zero-Trust Agent Discovery\n\n**No human app-store reviewer.** Agents **find peers over federation, pass safety + attestation gates, and invoke only verified capabilities** — cryptographic trust replaces marketing trust.\n\n| | |\n|---|---|\n| **What** | Federated `discover` → safety / reputation / TEE plugins → routed invoke |\n| **Why** | Scales to millions of micro-capabilities; malicious listings can’t drain channels |\n| **Deep dive** | [docs/killer-feature-zero-trust-discovery.md](https://github.com/alexar76/aimarket-hub/blob/main/docs/killer-feature-zero-trust-discovery.md) · [Ecosystem capabilities](https://github.com/alexar76/aicom/blob/main/docs/killer-features.md) |\n\n---\n\n## Architecture\n\n### System context\n\n```mermaid\nC4Context\n  title AIMarket Hub — system context\n\n  Person(consumer, \"Consumer\", \"App, agent, or widget user\")\n  Person(provider, \"Provider\", \"Lists capabilities on a hub\")\n\n  System(hub, \"AIMarket Hub\", \"Search, route, invoke, settle\")\n  System_Ext(peers, \"Peer hubs\", \"Federated catalogs\")\n  System_Ext(factory, \"AI-Factory\", \"Shipped products → capabilities\")\n  System_Ext(chain, \"Base L2\", \"USDT channels\")\n\n  Rel(consumer, hub, \"discover · channel · invoke\")\n  Rel(provider, hub, \"manifest · capabilities\")\n  Rel(hub, peers, \"crawl · route\")\n  Rel(hub, factory, \"import shipped products\")\n  Rel(hub, chain, \"open/close channel\")\n```\n\n### Container diagram (this repository)\n\n```mermaid\nflowchart TB\n  subgraph hub_process[\"aimarket_hub (FastAPI)\"]\n    API[\"api.py — REST /ai-market/v2/*\"]\n    CRW[\"crawler.py — BFS federation\"]\n    DB[\"database.py — capability index\"]\n    CH[\"channels.py — ledger + settle\"]\n    SG[\"safety_gate.py\"]\n    PR[\"plugin.py — PluginRegistry\"]\n    FB[\"factory_bridge.py\"]\n    SIG[\"signing.py — Ed25519 manifests\"]\n  end\n\n  subgraph plugins[\"plugins/ (entry_points)\"]\n    P1[\"safety · provenance · channels …\"]\n  end\n\n  subgraph storage[\"Persistence\"]\n    SQL[(\"SQLite / PostgreSQL\")]\n  end\n\n  API --> CRW\n  API --> DB\n  API --> CH\n  API --> SG\n  API --> PR\n  API --> FB\n  CRW --> DB\n  FB --> DB\n  DB --> SQL\n  PR --> P1\n  P1 -.->|\"pre/post hooks\"| API\n```\n\n### Factory import path\n\nShipped AI-Factory products are indexed as local capabilities on hub startup:\n\n```mermaid\nsequenceDiagram\n  participant Factory as AI-Factory pipeline.db\n  participant Loader as factory_products_loader\n  participant Bridge as factory_bridge\n  participant Index as database (SQLite)\n\n  Note over Factory,Index: On hub startup or sync script\n  Factory->>Loader: COMPLETED / DEPLOYED products\n  Loader->>Bridge: normalize capabilities\n  Bridge->>Index: upsert source_hub=local\n  Index-->>Bridge: indexed count\n```\n\nSync ops: [`../scripts/sync_pipeline_mirror_and_hub.py`](https://github.com/alexar76/aicom/blob/main/scripts/sync_pipeline_mirror_and_hub.py)\n\n---\n\n## Repository layout\n\n```\naimarket-hub/\n├── aimarket_hub/           # Core package\n│   ├── api.py              # HTTP routes (search, invoke, federation, plugins)\n│   ├── crawler.py          # Peer discovery (SSRF-hardened BFS)\n│   ├── database.py         # Capability + peer index\n│   ├── channels.py         # Payment channel ledger\n│   ├── plugin.py           # setuptools aimarket.plugins loader\n│   ├── factory_bridge.py   # AI-Factory product import\n│   ├── safety_gate.py      # Built-in safety fallback\n│   └── …\n├── plugins/                # Hub-local plugins (e.g. aimarket-provenance)\n├── tests/                  # pytest suite\n├── Dockerfile\n├── LICENSE                 # Apache-2.0\n├── CONTRIBUTORS.md\n├── SECURITY.md\n└── docs/\n    └── value.md\n```\n\n**Sibling packages** (monorepo root [`plugins/`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/)): 15 plugins — **top-5 on PyPI** ([install guide](https://github.com/alexar76/aimarket-plugins/blob/main/plugins/docs/install.md)); full set bundled in Docker.\n\n---\n\n## Quick start\n\n### Prerequisites\n\n- Python **3.11+**\n- Optional: Docker for container deploy\n\n### Install & run\n\n```bash\npip install aimarket-hub\n# optional core plugins (TEE, channels, reputation, safety, MCP packager):\npip install \"aimarket-hub[plugins]\"\naimarket serve\n# → http://localhost:9083\n```\n\nVerify discovery and search:\n\n```bash\ncurl -s http://localhost:9083/.well-known/ai-market.json | jq .\ncurl -s \"http://localhost:9083/ai-market/v2/search?intent=translate&budget=1\" | jq .\ncurl -s http://localhost:9083/ai-market/v2/plugins | jq '.plugins | length'\n```\n\n### Publish a capability (community providers)\n\nThird-party developers list an HTTP endpoint in the catalog and earn USDC when agents invoke it. **Production hubs** require stake, LUMEN trust scoring, and Ed25519-signed provider responses — see [`docs/supply-security.md`](https://github.com/alexar76/aimarket-hub/blob/main/docs/supply-security.md).\n\n```bash\ncd examples/hello-capability && python3 server.py   # terminal 1 — prints provider_pubkey\nexport AIMARKET_ALLOW_LOCAL_PUBLISH=1               # dev only\n# production: POST /ai-market/v2/supply/stake first, with your own credential and a\n# tx_hash for EVERY positive amount — the deposit is verified on-chain and single-use,\n# whatever its size, so sub-minimum drip-feeding cannot reach the stake gate.\naimarket publish capability.json --hub http://127.0.0.1:9083\naimarket invoke demo-hello/greet@v1 --input '{\"name\":\"dev\"}'\n```\n\nFull walkthrough (20 languages): [ARGUS developer guide](https://github.com/alexar76/argus/tree/main/docs/developer-guide/) · [supply security](https://github.com/alexar76/aimarket-hub/blob/main/docs/supply-security.md) · example in [`examples/hello-capability/`](https://github.com/alexar76/aimarket-hub/tree/main/examples/hello-capability).\n\n### Docker\n\n**Production (this monorepo):** always redeploy Hub from repo root:\n\n```bash\n./scripts/deploy_hub.sh\n# or full fleet: ./scripts/deploy_ecosystem.sh\n```\n\nSee [`docs/deploy-ecosystem.md`](https://github.com/alexar76/aicom/blob/main/docs/deploy-ecosystem.md). Do **not** use `cd aimarket-hub && docker compose up` for production redeploy (wrong build context).\n\n**Recovery** (factory hold, backup/restore, fleet redeploy): [`docs/recovery-mechanisms.md`](https://github.com/alexar76/aicom/blob/main/docs/recovery-mechanisms.md) in the factory monorepo.\n\nManual build (same as deploy script):\n\n```bash\ndocker build -f aimarket-hub/Dockerfile -t modelmarket-hub .\ndocker run -p 9083:9083 \\\n  -e AIMARKET_HUB_NAME=\"My Hub\" \\\n  -e AIMARKET_HUB_URL=\"https://my-hub.example.com\" \\\n  -e AIMARKET_PAYMENT_RECIPIENT=\"0xYourWallet\" \\\n  modelmarket-hub\n```\n\n---\n\n## Core API\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `GET` | `/.well-known/ai-market.json` | Root discovery — chain, token, peers, signer key |\n| `GET` | `/ai-market/v2/manifest` | Ed25519-signed capability catalog |\n| `GET` | `/ai-market/v2/search` | NL federated search (`intent`, `budget`, `category`) |\n| `POST` | `/ai-market/v2/supply/stake` | Deposit publisher stake (unlock community publish) |\n| `POST` | `/ai-market/v2/supply/register` | Publish community capability + `invoke_url` |\n| `POST` | `/ai-market/v2/invoke` | Invoke capability (plugin hooks, safety gate) |\n| `POST` | `/ai-market/v2/channel/open` | Open pre-funded payment channel |\n| `POST` | `/ai-market/v2/channel/close` | Close channel — settle + refund remainder |\n| `POST` | `/ai-market/v2/federation/announce` | Peer hub announcement |\n| `GET` | `/ai-market/v2/federation/peers` | Known peers + trust scores + pin status (`key_mismatch`) |\n| `GET` | `/ai-market/v2/federation/assay` | Last sandbox scorecard (`pass` auto-admits by default) |\n| `POST` | `/ai-market/v2/federation/assay` | Admin: re-run SSRF / signature / sandbox assay |\n| `POST` | `/ai-market/v2/federation/crawl` | Trigger BFS crawl of seed peers |\n| `POST` | `/ai-market/v2/federation/peers/approve` | Admin: toggle peer `trusted` (anti-TOFU) |\n| `POST` | `/ai-market/v2/federation/peers/repin` | Admin: rotate a sticky peer pin after legitimate key change |\n| `GET` | `/ai-market/v2/plugins` | Loaded plugin catalog |\n| `GET` | `/ai-market/v2/reputation/{hub_url}` | Trust score breakdown |\n| `GET` | `/ai-market/v2/stats/live` | Real-time invocation feed |\n\n**Authorization.** `/supply/register` takes the shared `AIMARKET_PUBLISH_TOKEN`. The routes that\nmove or encumber stake — `/supply/stake` and `/self-bond/register` — take the caller's OWN\ncredential from `AIMARKET_PUBLISHER_TOKENS` (or `AIMARKET_ADMIN_TOKEN`), because a shared token\ncannot prove which publisher is calling; in production a hub with neither configured refuses\nthem with `503`. `/self-bond/slash` and every settlement/federation route are admin-only.\n\nOpenAPI: `/docs` (FastAPI's default — there is no `AIMARKET_OPENAPI` switch; put the hub behind\nyour proxy if the schema should not be public). Full spec: [`../aimarket-protocol/spec.md`](https://github.com/alexar76/aimarket-protocol/blob/main/spec.md)\n\n---\n\n## Invoke lifecycle\n\nStandard consumer flow (implemented by [`aimarket_agent`](https://github.com/alexar76/aimarket-sdks/tree/main/dart/)):\n\n```mermaid\nsequenceDiagram\n  autonumber\n  participant Client\n  participant Hub as AIMarket Hub\n  participant Plugins\n  participant Target as Provider / local invoke\n\n  Client->>Hub: search(intent, budget)\n  Hub-->>Client: plan[]\n\n  Client->>Hub: channel/open(deposit_usd)\n  Hub-->>Client: channel_id\n\n  Client->>Hub: invoke(capability_id, input, channel_id)\n  Hub->>Plugins: on_invoke_pre_check\n  alt rejected\n    Plugins-->>Hub: signed rejection\n    Hub-->>Client: 403 + channel refund\n  else ok\n    Hub->>Target: forward or local execute\n    Target-->>Hub: output, price_usd\n    Hub->>Plugins: on_invoke_post_check\n    Hub-->>Client: result + provenance_receipt\n  end\n\n  Client->>Hub: channel/close(channel_id)\n  Hub-->>Client: settlement + unused balance\n```\n\n---\n\n## Plugin ecosystem\n\nPlugins register via **`aimarket.plugins`** entry points ([`plugin.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/plugin.py)). Each ships **README + docs/** (`value.md`, `user-guide.md`, `sdk-integration.md`, `user-cases.md`).\n\nRegenerate docs: `python3 scripts/bootstrap_hub_plugin_docs.py` · value text: `python3 scripts/bootstrap_product_value.py`\n\n```mermaid\nflowchart LR\n  INV[\"POST /invoke\"] --> PRE[\"pre-check\"]\n  PRE --> S[\"aimarket-safety\"]\n  PRE --> Z[\"aimarket-zk\"]\n  PRE --> PR[\"aimarket-promo\"]\n  PRE --> RUN[\"Execute\"]\n  RUN --> POST[\"post-check\"]\n  POST --> PV[\"aimarket-provenance\"]\n  POST --> T[\"aimarket-tee\"]\n  POST --> R[\"aimarket-reputation\"]\n  POST --> OUT[\"Response\"]\n```\n\n| Plugin | Category | One-line value |\n|--------|----------|----------------|\n| [`aimarket-provenance`](https://github.com/alexar76/aimarket-hub/tree/main/plugins/aimarket-provenance) | compliance | Cryptographic receipt per AI output |\n| [`aimarket-safety`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-safety/) | security | Block jailbreak / injection before billing |\n| [`aimarket-reputation`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-reputation/) | reputation | Stake-backed trust scores |\n| [`aimarket-channels`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-channels/) | infrastructure | Off-chain ledger, on-chain settlement |\n| [`aimarket-tee`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-tee/) | security | Hardware attestation (Nitro / TDX) |\n| [`aimarket-auction`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-auction/) | monetization | Spot bidding for scarce slots |\n| [`aimarket-personas`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-personas/) | tooling | Buyer-friendly agent personas |\n| [`aimarket-streaming`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-streaming/) | monetization | SSE + per-token micro-billing |\n| [`aimarket-nft`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-nft/) | monetization | Transferable prepaid credit NFTs |\n| [`aimarket-mcp-packager`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-mcp-packager/) | tooling | MCP bundle for Claude Desktop |\n| [`aimarket-orchestrator`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-orchestrator/) | monetization | NL task → capability chain planner |\n| [`aimarket-data-cap`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-data-cap/) | monetization | Private corpus → paid search |\n| [`aimarket-promo`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-promo/) | monetization | Signed time-locked discounts |\n| [`aimarket-dataset`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-dataset/) | tooling | Weekly anonymized demand corpus |\n| [`aimarket-zk`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/aimarket-zk/) | security | ZK proofs without revealing input |\n\n---\n\n## Federation\n\nHubs discover each other without a central registry:\n\n```mermaid\nflowchart TB\n  SEED[\"AIMARKET_SEED_LIST<br/>.well-known URLs\"] --> CRAWL[\"crawler.py BFS\"]\n  CRAWL --> MANIFEST[\"Fetch signed manifests\"]\n  MANIFEST --> INDEX[\"database.py\"]\n  INDEX --> SEARCH[\"Unified federated search\"]\n\n  HUB_A[\"Hub A\"] <-->|announce / peers| HUB_B[\"Hub B\"]\n  CRAWL --> HUB_A\n  CRAWL --> HUB_B\n\n  INV[\"invoke to remote capability\"] --> ROUTE[\"Route to peer hub\"]\n  ROUTE --> FEE[\"Optional routing_fee_bps\"]\n```\n\n### Observation gossip — seeing every new Hub\n\nHub addresses are always accepted through two public observation doors, and both lead to\n**quarantine**:\n\n- `POST /federation/announce` accepts an unauthenticated announcement;\n- a hub that crawls this one identifies itself with `X-AIMarket-Crawler` and is recorded\n  from that alone — so an operator can finally see who reads them.\n\nIn both cases the peer lands `status=pending`, `trusted=false`. Its manifest is **not**\nindexed and its capabilities are **not** searchable or routable. Its address is republished\nin the signed `observed_hubs` section of this hub's `.well-known`, so trusted peers learn it\non later crawl cycles and Alien Monitor renders it as unapproved. With\n`AIMARKET_FEDERATION_PREVIEW_CAPS=1` its manifest is\nfetched and signature-verified into a separate preview table so the operator can see what\nit offers before deciding — a table no search, routing or invoke path reads.\n\nObservation changes who is visible. Trust is not granted on the knock: the peer\nlands `pending`. A **sandbox assay** then runs in the background (and again on\ncrawl cycles). A `pass` auto-admits (`trusted` + crawl) so an operator is not\nclicking Approve for every capability. Fail and review stay at `/operator`.\n\nThe assay scores the **live invoke**, never brochure text. Names and descriptions\nare stripped before any model sees evidence. An optional LLM judge is **veto-only**\n(`AIMARKET_FEDERATION_JUDGE_URL`) — it cannot mint a pass from marketing copy.\n`AIMARKET_FEDERATION_ASSAY_LLM` is ignored if set. Factory analog:\n`product_automated_verify` (score running artifacts, not listings).\n\n| Variable | Default | Effect |\n|---|---|---|\n| `AIMARKET_FEDERATION_GOSSIP_MAX_OBSERVED` | `2000` | Resource/fan-out bound for quarantined observed addresses |\n| `AIMARKET_FEDERATION_OPEN` | `0` | Legacy switch for richer preview/admission behaviour; visibility is always on |\n| `AIMARKET_FEDERATION_PREVIEW_CAPS` | `1` | Signature-verified preview of a pending peer's catalogue |\n| `AIMARKET_FEDERATION_PREVIEW_MAX_CAPS` | `25` | Per-peer preview cap |\n| `AIMARKET_FEDERATION_ASSAY` | `1` | Post-quarantine sandbox assay |\n| `AIMARKET_FEDERATION_ASSAY_SANDBOX` | `1` | Probe one public free capability (receipt must match advertised key) |\n| `AIMARKET_FEDERATION_AUTO_ADMIT` | `1` | A `pass` sets `trusted` **only with a judge token**. Alias: `AIMARKET_FEDERATION_ASSAY_AUTO_TRUST` |\n| `AIMARKET_FEDERATION_JUDGE_URL` | OpenRouter chat if a key exists | OpenAI-compatible veto on sandbox evidence |\n| `AIMARKET_FEDERATION_JUDGE_KEY` | `OPENROUTER_API_KEY` fallback | **No key → manual Approve only** |\n| `AIMARKET_FEDERATION_JUDGE_MODEL` | `minimax/minimax-m3` | MiniMax, same as the rest of the fleet |\n| `AIMARKET_FEDERATION_JUDGE_REQUIRED` | `0` | If `1`, a judge error blocks auto-admit (also implied when auto-admit + key) |\n| `AIMARKET_FEDERATION_ASSAY_REQUIRE` | `0` | If `1`, human Approve refuses unless last assay is `pass` |\n\nJoin path: [`docs/join-the-federation.md`](https://github.com/alexar76/aicom/blob/main/docs/join-the-federation.md) · internals: [`docs/federation-admission.md`](docs/federation-admission.md) (EN·RU·ES·FR·ZH).\n\nSurfaces: `GET /federation/peers` (`pending` array) and `GET /federation/preview?url=…` are\n**public** — anyone can see who knocked and what they claim to offer; `GET /federation/inbound`\nis **admin-only** (who crawled us, no client IPs stored), and `DELETE /federation/peers?url=…`\nlets an operator reject a pending peer and drop its preview rows. The operator desk at\n`/operator` is the password-gated exception path (paid-only hubs, vetoes, dismissals; same\ntoken as `AIMARKET_ADMIN_TOKEN`). The terminal has a dedicated **Knocking** tile and **Unapproved hubs**\nrail (preview only). Alien Monitor has a **KNOCKS** button that\nopens the asking-in list on the LIVE map; UNI filters them out.\n\n### x402 interoperability\n\nThe hub speaks [x402](https://docs.x402.org/) — the machine-payment standard that became a\nLinux Foundation project in July 2026 — alongside its own payment surface:\n\n- a `402` from this hub's own payment gate carries the x402 **V2** payload in a base64\n  `PAYMENT-REQUIRED` header (a peer's 402 passed through verbatim is left untouched — its\n  terms are the peer's, not ours), and the\n  **V1** `accepts` array merged additively into the body, so both generations of client can\n  read it and existing consumers see no change;\n- `GET /discovery/resources` serves a **Bazaar-compatible** index of priced capabilities —\n  the same envelope every official x402 SDK deserializes, so pointing a facilitator client\n  at this hub enumerates its catalogue with no code changes.\n\nAccepting an x402 `PAYMENT-SIGNATURE` is deliberately **not** implemented: that means\nverifying and settling an EIP-3009 authorization, and moving money is not a change that\nshould ride along with a discovery change. See [`aimarket_hub/x402.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/x402.py).\n\nFull walkthrough: [`../docs/join-the-federation.md`](https://github.com/alexar76/aicom/blob/main/docs/join-the-federation.md) ·\nNormative text: protocol spec §2.4–2.6.\n\nTrust scoring: [`trust.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/trust.py) · Signing: [`signing.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/signing.py)\n\nPeer key pin / mismatch / admin re-pin (EN·RU·ES·FR·ZH): [`docs/federation-peer-keys.md`](./docs/federation-peer-keys.md)\n\nDeep dive: [`../docs/FEDERATION_HUB_REPORT.md`](https://github.com/alexar76/aicom/blob/main/docs/FEDERATION_HUB_REPORT.md)\n\n---\n\n## Payments\n\n```mermaid\nsequenceDiagram\n  participant User\n  participant Hub\n  participant Chain as Base (USDC)\n\n  User->>Chain: deposit USDC\n  User->>Hub: channel/open(deposit_usd)\n  Note over Hub: Ledger tracks balance off-chain\n\n  loop each invoke\n    User->>Hub: invoke + X-Payment-Channel\n    Hub->>Hub: decrement channel balance\n  end\n\n  User->>Hub: channel/close\n  Hub->>Chain: settle spent + refund remainder\n```\n\n| Field | Default | Notes |\n|-------|---------|-------|\n| Chain | Base (L2) | `AIMARKET_PAYMENT_CHAIN` |\n| Token | USDC | `AIMARKET_PAYMENT_TOKEN` — the ledger's default; the advertised catalog is `AIMARKET_PAYMENT_TOKENS` (`USDT,USDC,ETH`) |\n| Recipient | env required | `AIMARKET_PAYMENT_RECIPIENT` |\n\nProtocol principle: **no custody** — channels are on-chain constructs; hub holds ledger state only.\n\n**Deposit authorization.** In production (`AIFACTORY_PROD=1`, verify stub off) a channel is credited\nonly by a deposit that is verified on-chain, bound to the wallet that actually paid, single-use\n(`consumed_deposits`), and proven by an EIP-191 signature from the paying wallet over\n`payer_proof_challenge(...)` — the deposit tx hash is public, so without that proof the channel\nsecret would go to whoever quotes it first. `AIMARKET_CHANNEL_ALLOW_UNPROVEN_PAYER=1` opts out of\nthe proof (transition only) and logs loudly.\n\n---\n\n## Pay-on-Verified\n\n**Opt-in quality escrow on invoke.** With a `verify` block on the invoke body the channel debit\nbecomes a hold; [Metis](https://github.com/alexar76/metis) judges the delivered output against the\nbuyer's stated intent in the background — pass captures the hold, fail refunds it with a signed\nrejection receipt. The buyer keeps the output either way; only the money outcome changes.\n\n| | |\n|---|---|\n| **What** | `verify: { requested, intent, mode, wait }` on `POST /ai-market/v2/invoke` → `hold_channel` → Metis verdict → capture / release |\n| **Why** | Providers are paid for verified work, not for responding; every verdict emits a reputation event |\n| **Lookup** | `GET /ai-market/v2/verification/{nonce}` (nonce = receipt nonce) |\n| **Deep dive** | [docs/pay-on-verified.md](https://github.com/alexar76/aimarket-hub/blob/main/docs/pay-on-verified.md) · [Cross-component doc](https://github.com/alexar76/aicom/blob/main/docs/pay-on-verified.md) |\n\n---\n\n## Configuration\n\nEvery default below is the value the code falls back to today; where a default is *derived*\nfrom another variable, the rule is spelled out rather than a number.\n\n### Core\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `AIMARKET_HUB_NAME` | AIMarket Hub | Display name in manifests |\n| `AIMARKET_HUB_URL` | `http://localhost:9083` | Public URL (receipts, well-known) |\n| `AIFACTORY_PROD` | — | `1` puts every money gate on the production path (on-chain verification required, fail-closed defaults) |\n| `AIFACTORY_CRYPTO_ENABLED` | `0` | Master crypto switch: off ⇒ channels/escrow/NFT disabled, capabilities served free; signing and sandbox trials keep working |\n| `AIMARKET_PAYMENT_CHAIN` | `base` | Settlement chain (`AIMARKET_PAYMENT_CHAINS` for the advertised list) |\n| `AIMARKET_PAYMENT_TOKEN` | `USDC` | Ledger settlement token (`AIMARKET_PAYMENT_TOKENS` advertises `USDT,USDC,ETH`) |\n| `AIMARKET_PAYMENT_RECIPIENT` | — | **Required in production** — the wallet deposits must pay |\n| `AIMARKET_CRAWL_INTERVAL_S` | `3600` | Federation crawl period |\n| `AIMARKET_ROUTING_FEE_BPS` | `100` | Routing fee (1% = 100 bps) |\n| `AIMARKET_MIN_TRUST_SCORE` | `0.3` | Baseline trust floor (also the discover-gate default below) |\n| `AIMARKET_SEED_LIST` | committed `federation_seeds.json` | Comma-separated peer `.well-known` URLs; unset falls back to the shipped seed file, not to \"no seeds\" |\n| `AIMARKET_SEED_PUBKEYS` | committed seed `public_key` fields | `{url:key}` JSON or `url=key,…` — trusted-on-**first-contact** only; rotating an existing DB pin requires `POST /federation/peers/repin` |\n| `AIMARKET_PLUGIN_WHITELIST` | — | Restrict loaded plugins |\n| `AIMARKET_ADMIN_TOKEN` | — | Operator token. Unset ⇒ every admin route refuses (`503`), fail-closed |\n| `AIMARKET_PUBLISH_TOKEN` | — | Shared token for `/supply/register`. Unset ⇒ publish disabled |\n| `AIMARKET_PUBLISHER_TOKENS` | — | `pub-a:secretA,pub-b:secretB` — per-publisher credentials for the stake/bond routes (see Security) |\n| `AIMARKET_CORS_ORIGINS` | — | Comma-separated allowlist. Empty means no cross-origin access (a `*` default enabled drive-by CSRF) |\n\n### Databases\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `DATABASE_URL` | SQLite files | PostgreSQL for production — when set, every subsystem shares it |\n| `AIMARKET_DB_PATH` | `data/hub.db` | The **hub index** database. It no longer overrides a path a subsystem passes explicitly (that silently aliased channels.db and provenance.db onto the hub file); a subsystem that must share the hub file now points its own variable at it |\n| `AIMARKET_CHANNELS_DB_PATH` | `data/channels.db` | Payment-channel ledger (separate file from the hub index) |\n| `AIMARKET_VERIFY_SETTLEMENTS_DB_PATH` | `AIMARKET_DB_PATH`, else `data/hub.db` | Where `verified_settlements` lives — the orphaned-hold reaper reads it and refuses to release anything it cannot read |\n\n#### Upgrading past the shared-database aliasing\n\n**This is a one-time migration step for any hub that already ran with `AIMARKET_DB_PATH`\nset** — which includes every container here (`Dockerfile`, `Dockerfile.standalone`,\n`docker-compose.yml`, `docker-compose.core.yml` all export it).\n\nUntil this release the env var overrode the path a subsystem asked for, so the channel\nledger (`data/channels.db`) and the provenance store (`data/provenance.db`) were created\n*inside the hub file*. Now that the explicit argument wins, those subsystems open their own\nfiles — and on an upgraded deployment those files **start empty**:\n\n* the channel ledger loses its open channels and, more seriously, `consumed_deposits` —\n  the table that makes an on-chain deposit single-use. An empty one lets every deposit\n  already spent be replayed into a new funded channel;\n* the provenance store loses its receipts.\n\nThe hub logs this at `ERROR` on startup (the requested file does not exist while the\n`AIMARKET_DB_PATH` file does), naming the file the data is still in. Do one of these\n**before serving traffic**:\n\n```bash\n# A. channel ledger — keep the shared file, no data moves, pre-upgrade behaviour exactly\nexport AIMARKET_CHANNELS_DB_PATH=\"$AIMARKET_DB_PATH\"\n\n# B. channel ledger — split it out: copy the file with the hub stopped\ncp /app/data/hub.db /app/data/channels.db\nexport AIMARKET_CHANNELS_DB_PATH=/app/data/channels.db\n```\n\nEither way the tables the copy's owner does not use are simply never read. The provenance\nstore has **no** path variable — it always derives `provenance.db` from the hub database's\ndirectory — so B is the only option there (`cp /app/data/hub.db /app/data/provenance.db`);\nskipping it starts an empty receipt store, which costs an audit trail but no money.\n\n`DATABASE_URL` deployments are unaffected — PostgreSQL was always one shared database.\n\n### Channels\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `AIMARKET_ALLOW_DEMO_CREDIT` | — | `1` credits a channel without on-chain verification (dev/demo). Outside production, without it, crediting fails closed |\n| `AIMARKET_CHANNEL_ALLOW_UNPROVEN_PAYER` | `0` | `1` opts OUT of the payer proof-of-control requirement (transition only — leaves deposit front-running open) |\n| `AIMARKET_CHANNEL_ANON_OPENS_PER_HOUR` | `200` | One shared cap for all wallet-less opens (they are not exempt) |\n| `AIMARKET_CHANNEL_ANON_CLOSES_PER_HOUR` | `600` | Same, for closes |\n| `AIMARKET_CHANNEL_HOLD_REAP_AFTER_SECS` | `86400` | Release a hold stuck `held` this long with no live verification; `0` disables the reaper |\n| `AIFACTORY_PAYMENT_MIN_CONFIRMATIONS` | `2` | Confirmations a deposit needs before it counts |\n| `AIFACTORY_PAYMENT_VERIFY_STUB` | `0` | `1` accepts any tx hash — development only |\n\n### Pay-on-Verified\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `AIMARKET_VERIFY_ENABLED` | `1` | Pay-on-Verified master switch (per-invoke opt-in still required) |\n| `AIMARKET_VERIFY_MIN_PRICE_USD` | `0.05` | Price floor — cheaper invokes are never verification-taxed |\n| `AIMARKET_VERIFY_SCORE_THRESHOLD` | `0.7` | `verify_score` needed to capture the hold (a value outside 0.0–1.0 falls back to `0.7`) |\n| `AIMARKET_VERIFY_COUNCIL_MIN_PRICE_USD` | `0.50` | Route ceiling: `council` allowed at/above this price, else clamped to `fast` |\n| `AIMARKET_VERIFY_MAX_CONCURRENCY` | `8` | Cap on simultaneous Metis calls across pending settlements |\n| `AIMARKET_VERIFY_ATTEMPT_TIMEOUT_S` | `330` | Per-attempt Metis HTTP timeout (> Metis 300 s server cap) |\n| `AIMARKET_VERIFY_RETRY_BACKOFF_S` | `5` | Initial transport-retry backoff (exponential, cap 300 s) |\n| `AIMARKET_VERIFY_ENGINE_RETRIES` | `2` | Re-runs after an engine-error envelope before policy applies |\n| `AIMARKET_VERIFY_MAX_WAIT_S` | `0` | `0` = no verdict deadline; `>0` bounds resolution via policy |\n| `AIMARKET_VERIFY_FAIL_CLOSED` | `1` | Indeterminate outcome ⇒ refund the buyer. Only an explicit `0/false/no/off` captures instead; an unrecognised value is a typo and still fails closed |\n| `AIMARKET_VERIFY_METIS_URL` | `http://127.0.0.1:8080` | Metis base URL (falls back to `METIS_URL`) |\n| `AIMARKET_VERIFY_METIS_KEY` | — | Metis bearer key (falls back to `METIS_API_KEY`) |\n| `AIMARKET_VERIFY_VERIFIER_ID` | `metis.verify@v1` | Envelope `verifier` attribution when a non-Metis verifier serves the slot |\n\n### Supply security (community publishers)\n\nFull model: [`docs/supply-security.md`](https://github.com/alexar76/aimarket-hub/blob/main/docs/supply-security.md). A non-finite or non-numeric\nvalue in any threshold below is ignored with a warning and the documented default is used — a\n`nan` threshold would otherwise silently disable the gate it configures.\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `AIMARKET_SUPPLY_SECURITY_RELAXED` | `0` | `1` = dev bypass: zero minimum stake, no response-signature requirement, no slashing |\n| `AIMARKET_SUPPLY_MIN_STAKE_USD` | `25` in production, else `10` (`0` when relaxed) | Stake required to publish |\n| `AIMARKET_SUPPLY_PUBLISH_PER_HOUR` | `5` | Publishes per publisher per hour |\n| `AIMARKET_SUPPLY_MIN_TRUST_DISCOVER` | `AIMARKET_MIN_TRUST_SCORE` (`0.3`) | Trust floor to appear in discover |\n| `AIMARKET_SUPPLY_MIN_TRUST_INVOKE` | `0.35` | Trust floor to be invoked |\n| `AIMARKET_SUPPLY_REQUIRE_RESPONSE_SIG` | on iff production and not relaxed | Require an Ed25519 provider response signature |\n| `AIMARKET_SUPPLY_MAX_INPUT_KEYS` | `32` | Top-level keys accepted in an invoke input |\n| `AIMARKET_SUPPLY_MAX_INPUT_JSON_BYTES` | `32768` | Invoke input size cap |\n| `AIMARKET_SUPPLY_PRODUCT_ALLOWLIST` | — | Comma-separated `product_id` allowlist |\n| `AIMARKET_SUPPLY_SLASH_FAILURE_THRESHOLD` | `3` | Provider faults within the window before stake is slashed |\n| `AIMARKET_SUPPLY_SLASH_FAILURE_WINDOW_S` | `600` | Fault window (must be > 0; a non-positive value would disable slashing, so it falls back) |\n| `AIMARKET_SUPPLY_SLASH_COOLDOWN_S` | `3600` | At most one failure-driven slash per window; `0` disables the cool-down |\n| `AIMARKET_SUPPLY_SLASH_DAILY_CAP_USD` | `10` | Rolling 24 h cap on failure-driven slashing; `0` disables the cap |\n| `AIMARKET_SUPPLY_VERIFIED_FAIL_THRESHOLD` | `3` | Paid Metis \"failed\" verdicts before escalation |\n| `AIMARKET_SUPPLY_VERIFIED_FAIL_WINDOW_S` | `86400` | Window for those verdicts |\n| `AIMARKET_SUPPLY_VERIFIED_FAIL_MIN_CONSUMERS` | `2` | Distinct PAYING consumers required — one buyer's repeated failures are one voice |\n| `AIMARKET_SUPPLY_TRUST_GRAPH_MAX_EDGES` | `1000` | Trust-graph bound; truncation is logged with the publisher it affected |\n| `AIMARKET_ORACLE_FAMILY_URL` | `https://oracles.modelmarket.dev/family` | LUMEN trust oracle (falls back to `ARGUS_ORACLE_FAMILY_URL`) |\n\n---\n\n## Deployment\n\n**Start here:** [complete production deployment runbook](docs/production-deployment.md). It is also available in [Russian](docs/production-deployment.ru.md), [Spanish](docs/production-deployment.es.md), [French](docs/production-deployment.fr.md) and [Chinese](docs/production-deployment.zh.md).\n\nThe runbook covers immutable commit-pinned releases, unprivileged systemd services, nginx/TLS on a hostname or `/hub` subpath, same-origin federation discovery and `invoke`, signed-manifest and real `402` assay evidence, protocol-only federation admission, UFW/Fail2ban/SSH hardening, backups, reboot acceptance, Alien Monitor and SKOPOS enrollment. Do not expose the provider backend or replace the Hub's Ed25519 key during a routine upgrade.\n\nReference record for the maintained public installation: [`../docs/production-modelmarket-dev.md`](https://github.com/alexar76/aicom/blob/main/docs/production-modelmarket-dev.md).\n\n---\n\n## Testing & coverage {#testing--coverage}\n\nCI runs on every push ([workflow](https://github.com/alexar76/aimarket-hub/blob/main/.github/workflows/ci.yml)); coverage badge is refreshed from `pytest --cov` on `main`.\n\n```bash\ncd aimarket-hub\npip install -e \".[dev]\"\npytest tests/ -q --cov=aimarket_hub\n```\n\n## Development\n\n```bash\npip install -e \".[dev]\"\n```\n\nKey test modules: `test_api.py`, `test_crawler.py`, `test_plugin_system.py`, `test_channels.py`, `test_cross_hub_integration.py`\n\nAdd a plugin: create package under [`../plugins/`](https://github.com/alexar76/aimarket-plugins/tree/main/plugins/) with `pyproject.toml` entry point `aimarket.plugins`.\n\n---\n\n## Security\n\n- **SSRF protection** on federation crawler ([`crawler.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/crawler.py))\n- **Signed manifests** — Ed25519 ([`signing.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/signing.py))\n- **Safety gate** on every invoke ([`safety_gate.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/safety_gate.py))\n- **Verified, single-use stake deposits** — in production every stake credit needs an on-chain\n  deposit that pays the platform recipient, and the hash is burned by an atomic claim before the\n  credit, so one deposit can never fund two publishers even under concurrent requests. The claim\n  is keyed on the *canonical* transaction id (an EVM hash is case-insensitive at the JSON-RPC\n  layer, so `0xAB…` and `0xab…` are one deposit, not two)\n  ([`supply_security.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/supply_security.py))\n- **Residual — stake deposits are not payer-bound.** The stake verifier answers \"did somebody pay\n  the platform?\", not \"did *this* publisher pay\", so whoever submits a matching hash first gets the\n  credit. Binding it needs a publisher→wallet record the stake ledger does not yet have; channel\n  deposits are already bound (see the entry below). Until then, treat a stake deposit hash as a\n  bearer secret and submit it before it is public\n- **Single-use channel deposits + payer proof** — a verified deposit funds exactly one channel and\n  only for the wallet that signed for it ([`channels.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/channels.py))\n- **Stake mutation is per-subject, slashing is operator-only** — a shared token can neither credit\n  a stranger's stake nor burn a rival's bond ([`api.py`](https://github.com/alexar76/aimarket-hub/blob/main/aimarket_hub/api.py))\n- **Vulnerability reports:** [SECURITY.md](https://github.com/alexar76/aimarket-hub/blob/main/SECURITY.md) → alexar76@rambler.ru\n\n---\n\n## Related projects\n\n| Project | Relationship |\n|---------|--------------|\n| [AICOM / AI-Factory](https://github.com/alexar76/aicom/blob/main/README.md) | Ships products → hub index |\n| [aimarket-protocol](https://github.com/alexar76/aimarket-protocol/tree/main/) | Normative v2 spec |\n| [aimarket-sdks](https://github.com/alexar76/aimarket-sdks/tree/main/) | Client SDKs (Dart alpha) |\n| [aimarket-widget](https://github.com/alexar76/aimarket-widget/tree/main/) | Embeddable UI |\n| [oracles](https://github.com/alexar76/oracles/tree/main/) | Verifiable math capabilities — randomness, VDF, consensus, reputation (listed on hub) |\n| [desktop-integrations](https://github.com/alexar76/aimarket-desktop/tree/main/) | 8 Flutter consumer apps |\n| [Ecosystem architecture](https://github.com/alexar76/aicom/blob/main/docs/ecosystem-architecture.md) | Full monorepo diagram |\n| [dioscuri](https://github.com/alexar76/dioscuri) | Twin community agents — MNEMOSYNE Q&A |\n\n---\n\n## Community\n\nThe [DIOSCURI](https://github.com/alexar76/dioscuri) twins answer questions from synced GitHub docs.\n\n| Channel | Twin | Best for |\n|---------|------|----------|\n| [Discord](https://discord.gg/aimarket) | Pollux | Help, ideas, show-and-tell |\n| [Telegram](https://t.me/just_for_agents) | Castor | Releases, digests, quick news |\n\n**Ecosystem map:** [Alien Monitor](https://monitor.modelmarket.dev/) · [AICOM](https://magic-ai-factory.com)\n\n---\n\n## License\n\nApache-2.0 — see [LICENSE](https://github.com/alexar76/aimarket-hub/blob/main/LICENSE). Maintainers: [CONTRIBUTORS.md](https://github.com/alexar76/aimarket-hub/blob/main/CONTRIBUTORS.md).\n",
  "bytes": 40653,
  "sha": "db9c88fcdd86a8a79f7b1840d2920822ad74509179a6bdb466c20a0bf0ee60dd",
  "repo_slug": "alexar76/aimarket-hub",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_alexar76_aimarket_hub_9de08651/readme"
}