From 99def9fe41279a6723d54aec6463a596009da8e4 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Tue, 17 Feb 2026 14:37:16 -0700 Subject: [PATCH 1/4] docs: blueprint auth, triggers, pricing, and gateways - Add auth proxy docs (blueprint-auth) - Add job trigger map plus dedicated Webhooks and x402 pages - Update pricing docs and note x402 settlement fields in pricing engine - Align runner docs with TangleProducer/TangleConsumer/TangleLayer - Add tnt-core protocol deployment pointers and refresh operator pricing Verification: yarn lint --- pages/developers/_meta.ts | 1 + pages/developers/blueprint-auth.mdx | 129 ++++++++++++++++++ pages/developers/blueprint-qos.mdx | 56 ++++++-- pages/developers/blueprint-runner/_meta.ts | 3 + .../developers/blueprint-runner/building.mdx | 10 +- .../developers/blueprint-runner/consumers.mdx | 24 ++-- .../blueprint-runner/introduction.mdx | 15 ++ .../blueprint-runner/job-triggers.mdx | 107 +++++++++++++++ pages/developers/blueprint-runner/jobs.mdx | 4 +- .../developers/blueprint-runner/producers.mdx | 20 +-- pages/developers/blueprint-runner/routers.mdx | 4 +- .../developers/blueprint-runner/webhooks.mdx | 91 ++++++++++++ pages/developers/blueprint-runner/x402.mdx | 100 ++++++++++++++ pages/developers/blueprint-sdk.mdx | 3 + pages/developers/blueprints/_meta.ts | 3 +- .../blueprints/pricing-and-payments.mdx | 113 +++++++++++++++ .../developers/blueprints/pricing-engine.mdx | 111 +++++++++------ pages/developers/p2p-networking/usage.mdx | 4 +- .../system-architecture/overview.mdx | 10 +- pages/infrastructure/_meta.ts | 1 + pages/infrastructure/protocol-deployment.mdx | 44 ++++++ pages/operators/pricing/overview.mdx | 100 +++++--------- pages/operators/quality-of-service.mdx | 7 +- pages/vision/architecture.mdx | 3 + pages/vision/core-concepts.mdx | 2 + pages/vision/introduction.mdx | 1 + pages/vision/use-cases.mdx | 2 + 27 files changed, 809 insertions(+), 159 deletions(-) create mode 100644 pages/developers/blueprint-auth.mdx create mode 100644 pages/developers/blueprint-runner/job-triggers.mdx create mode 100644 pages/developers/blueprint-runner/webhooks.mdx create mode 100644 pages/developers/blueprint-runner/x402.mdx create mode 100644 pages/developers/blueprints/pricing-and-payments.mdx create mode 100644 pages/infrastructure/protocol-deployment.mdx diff --git a/pages/developers/_meta.ts b/pages/developers/_meta.ts index 46c47872..3b1a8d9b 100644 --- a/pages/developers/_meta.ts +++ b/pages/developers/_meta.ts @@ -13,6 +13,7 @@ const meta: Meta = { }, "blueprint-contexts": "Contexts", "blueprint-runner": "Blueprint Runner", + "blueprint-auth": "Auth Proxy", "blueprint-qos": "Quality of Service", "p2p-networking": "P2P Networking", "-- tooling": { diff --git a/pages/developers/blueprint-auth.mdx b/pages/developers/blueprint-auth.mdx new file mode 100644 index 00000000..42528b34 --- /dev/null +++ b/pages/developers/blueprint-auth.mdx @@ -0,0 +1,129 @@ +--- +title: Blueprint Auth Proxy +description: How blueprint-manager enforces authn/authz for off-chain HTTP/gRPC services (multi-tenancy, scopes, OAuth, mTLS). +--- + +# Blueprint Auth Proxy (`blueprint-auth`) + +Blueprints often expose off-chain HTTP/gRPC endpoints (APIs, agents, gateways, etc.). In the Tangle Blueprint stack, +those endpoints are typically fronted by an **auth proxy** that runs inside `blueprint-manager`. + +That proxy is implemented by the `blueprint-auth` crate and is the **single enforcement point** for: + +- Authentication (API keys, OAuth assertions, mTLS) +- Authorization (scopes) +- Multi-tenancy (canonical tenant identity injection) +- Header hygiene (strip spoofable auth headers; validate forwarded headers) + +This page focuses on how **service users** obtain credentials and how **service developers** consume identity safely. + +Source of truth (implementation-focused): + +- Auth proxy flows and endpoints: https://github.com/tangle-network/blueprint/blob/v2/crates/auth/AUTH_WORKFLOW.md +- OAuth JWT bearer assertion policy: https://github.com/tangle-network/blueprint/blob/v2/crates/auth/src/oauth/README.md + +## What It Applies To (And What It Does Not) + +- Applies to: **off-chain** requests that go through the manager’s proxy to your service `upstream_url`. +- Does not apply to: **on-chain jobs** (`jobs submit`, contract calls). On-chain callers authenticate by signing transactions. + +## Key Concepts + +- `service_id`: Identifies the service behind the proxy. Minting endpoints require `X-Service-Id: `. +- Tenant identity: The proxy injects **`x-tenant-id`** (a privacy-safe hash) so upstreams can partition data safely. +- Scopes: The proxy can inject **`x-scopes`** (space-delimited) derived from an authorized token. +- Trust boundary: Upstreams should treat the proxy as the only trusted source of tenant/scopes headers. + +## How A User Gets An Access Token + +Users don’t generate `v4.local...` access tokens locally. They obtain them from the auth proxy by proving identity via +one of the supported mechanisms. + +### Option A: OAuth 2.0 JWT Bearer Assertion (Typical End-User Flow) + +If your service is configured with an OAuth policy, a user can exchange a signed JWT assertion for a short-lived access +token: + +1. The user authenticates with an issuer you trust (your IdP) and receives a signed JWT assertion containing `sub`, + `iss`, `iat`, `exp`, and a unique `jti`. +2. The user calls the proxy: + +```bash +curl -sS -X POST "http://:8276/v1/oauth/token" \ + -H "X-Service-Id: " \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \ + --data-urlencode "assertion=" +``` + +3. The proxy verifies the assertion (signature + claims + replay protection via `jti`) and returns a short-lived + `v4.local...` token. +4. The user calls your service through the proxy: + +```bash +curl -sS "http://:8276/" \ + -H "Authorization: Bearer v4.local.<...>" +``` + +What your upstream receives (conceptually): + +- `x-tenant-id`: derived from the verified OAuth `sub` (hashed) +- `x-scopes`: a normalized scope list if allowed by your per-service policy + +### Option B: API Key Exchange (Service Owner / Operator Flow) + +This is primarily for service owners/operators and automation: + +1. Owner proves control of a registered owner key (challenge/verify). +2. Proxy returns a long-lived API key (`ak_...`). +3. Owner exchanges the API key for a short-lived access token: + +```bash +curl -sS -X POST "http://:8276/v1/auth/exchange" \ + -H "Authorization: Bearer ak_." \ + -H "Content-Type: application/json" \ + -d '{"additional_headers": {"X-Tenant-Id": "optional-tenant-hint"}}' +``` + +### Option C: mTLS (High-Trust Environments) + +If a service is configured to require client mTLS, the client authenticates using a certificate trusted by the proxy. +The proxy can inject certificate identity headers (subject/issuer/serial) and an auth method header. + +## Multi-Tenancy: What Happens For A New User vs Existing User + +From the proxy’s perspective, multi-tenancy is **stateless**: + +- A “new user” is simply a request whose derived `x-tenant-id` has not been seen by your upstream before. +- An “existing user” is one whose derived `x-tenant-id` matches previously observed requests. + +The proxy is responsible for: + +- Deriving/injecting a canonical `x-tenant-id` after validating the caller +- Stripping any client-supplied `x-tenant-*` or `x-scopes` headers (prevent spoofing) +- Validating/normalizing any additional forwarded headers (size, count, forbidden headers) + +Your upstream is responsible for: + +- Using `x-tenant-id` as the partition key (database namespace, row-level filter, object prefix, etc.) +- Enforcing scope checks based on `x-scopes` (if your service uses scopes) +- Ensuring requests cannot bypass the proxy (network policy, firewall rules, service binding to localhost/private network) + +## Operator Notes (Manager Defaults) + +`blueprint-manager` runs the auth proxy by default and exposes CLI flags: + +- `--auth-proxy-host` (default `0.0.0.0`) +- `--auth-proxy-port` (default `8276`) + +See: https://github.com/tangle-network/blueprint/blob/v2/crates/manager/src/config/mod.rs + +## Configuration Status (OAuth Policy) + +OAuth verification is driven by a **per-service policy** (allowed issuers/audiences/public keys/scopes/TTL caps) +stored by `service_id`. + +At time of writing, the policy format and verification rules are implemented and tested, but operator-facing tooling for +managing policies may be limited. Start here: + +- Policy schema + rules: https://github.com/tangle-network/blueprint/blob/v2/crates/auth/src/oauth/README.md diff --git a/pages/developers/blueprint-qos.mdx b/pages/developers/blueprint-qos.mdx index 14355958..2e3a3718 100644 --- a/pages/developers/blueprint-qos.mdx +++ b/pages/developers/blueprint-qos.mdx @@ -2,6 +2,8 @@ title: Quality of Service (QoS) Integration --- +import GithubFileReaderDisplay from "/components/GithubFileReaderDisplay"; + # Quality of Service (QoS) Integration Guide SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/v2/crates/qos @@ -13,20 +15,25 @@ This guide explains how to integrate the Blueprint SDK Quality of Service (QoS) The Blueprint QoS system provides a complete observability stack: - **Heartbeat Service**: submits periodic liveness signals to the status registry -- **Metrics Collection**: exports system and job metrics via a Prometheus-compatible endpoint +- **Metrics Collection**: exports system and job metrics via a Prometheus-compatible HTTP endpoint - **Logging**: streams logs to Loki (optional) - **Dashboards**: builds Grafana dashboards (optional) -- **Server Management**: can run Grafana/Loki/Prometheus containers for you +- **Server Management**: can run Grafana and Loki (and optionally Prometheus) for you ## What QoS Exposes QoS always exposes a Prometheus-compatible metrics endpoint when metrics are enabled. Grafana and Loki are optional and can be managed by QoS or connected externally. -| Component | Default Endpoint | Notes | -| ------------------ | ------------------------------------- | ---------------------------------------------------------------------- | -| Prometheus metrics | `http://:9090/metrics` | Includes `/health` plus Prometheus v1 API routes like `/api/v1/query`. | -| Grafana UI | `http://:3000` | Only when configured or managed by QoS. | -| Loki push API | `http://:3100/loki/api/v1/push` | Only when configured or managed by QoS. | +| Component | Default Endpoint | Notes | +| ---------------- | ------------------------------------- | --------------------------------------------------------------------- | +| Metrics endpoint | `http://:9090/metrics` | Prometheus scrape format. Also exposes basic health and query routes. | +| Grafana UI | `http://:3000` | Only when configured or managed by QoS. | +| Loki push API | `http://:3100/loki/api/v1/push` | Only when configured or managed by QoS. | + +Notes: + +- The metrics endpoint is started when `QoSConfig.metrics` is enabled. If you want QoS without a metrics listener, set `metrics: None`. +- The query routes are provided for convenience and debugging. They are not a replacement for a full Prometheus deployment. ## Integrating QoS with BlueprintRunner @@ -43,7 +50,18 @@ BlueprintRunner::builder(TangleEvmConfig::default(), env) .await?; ``` -Note: `BlueprintRunner::qos_service` enables `manage_servers(true)` internally. If you want to avoid managed containers, pass a config with `grafana_server: None` and `loki_server: None`. +Important behavior: + +- `BlueprintRunner::qos_service` forces `manage_servers(true)` today. If you want to avoid managed containers, pass a config with `grafana_server: None` and `loki_server: None`. If you also do not want QoS to push logs, set `loki: None`. + +Reference: + + ## HeartbeatConsumer and Keystore Requirements @@ -83,17 +101,28 @@ impl HeartbeatConsumer for MyHeartbeatConsumer { let qos_config = blueprint_qos::default_qos_config(); ``` -This enables metrics, Loki logging, and Grafana integration. Whether containers start depends on `manage_servers` (BlueprintRunner forces it on; see note above). +This enables heartbeat, metrics, Loki logging, and Grafana integration. By default it also includes server configs for Grafana and Loki. If you run it via `BlueprintRunner::qos_service`, those servers will be started as managed containers unless you disable them in the config. + +Reference: + + ### Bring Your Own Observability Stack -Point QoS at your existing Grafana/Loki/Prometheus stack by overriding the configs and keeping `manage_servers` off: +If you use `QoSServiceBuilder` directly, you can keep `manage_servers(false)` and point QoS to your existing stack. + +If you use `BlueprintRunner::qos_service`, `manage_servers(true)` is forced. In that case, the way to avoid managed containers is to set the server configs to `None` while still pointing `GrafanaConfig` and `LokiConfig` at your external services. ```rust let qos_config = QoSConfig { metrics: Some(MetricsConfig { prometheus_server: Some(PrometheusServerConfig { - host: "0.0.0.0".into(), + host: "127.0.0.1".into(), port: 9090, use_docker: false, ..Default::default() @@ -110,7 +139,8 @@ let qos_config = QoSConfig { url: "http://loki.internal:3100/loki/api/v1/push".into(), ..Default::default() }), - manage_servers: false, + grafana_server: None, + loki_server: None, ..blueprint_qos::default_qos_config() }; ``` @@ -229,7 +259,7 @@ if let Some(qos) = &ctx.qos_service { - Initialize QoS early in your Blueprint startup sequence. - Use `BlueprintRunner::qos_service(...)` to auto-wire RPC + keystore + status registry. -- Keep Prometheus reachable (bind to `0.0.0.0` if scraped externally). +- Bind the metrics endpoint to `127.0.0.1` unless you explicitly want it scraped remotely. - Replace default Grafana credentials when using managed servers. ❌ DON'T: diff --git a/pages/developers/blueprint-runner/_meta.ts b/pages/developers/blueprint-runner/_meta.ts index 823f7e1d..bcd13570 100644 --- a/pages/developers/blueprint-runner/_meta.ts +++ b/pages/developers/blueprint-runner/_meta.ts @@ -5,6 +5,9 @@ const meta: Meta = { jobs: "Jobs", routers: "Routers", producers: "Producers", + "job-triggers": "Job Triggers", + webhooks: "Webhooks", + x402: "x402 Payments", consumers: "Consumers", "background-services": "Background Services", building: "Building a Blueprint Runner", diff --git a/pages/developers/blueprint-runner/building.mdx b/pages/developers/blueprint-runner/building.mdx index 00ebcd75..95087eb7 100644 --- a/pages/developers/blueprint-runner/building.mdx +++ b/pages/developers/blueprint-runner/building.mdx @@ -71,7 +71,7 @@ To build a Blueprint Runner, you need a producer to listen for events and a cons ### Step 4: Configuring the Router -The [router](/developers/blueprint-runner/routers) directs job calls to the appropriate handlers. In the example below, we configure the router with routes for our jobs and specify that they are on Tangle EVM with the `TangleEvmLayer`: +The [router](/developers/blueprint-runner/routers) directs job calls to the appropriate handlers. In the example below, we configure the router with routes for our jobs and specify that they are on Tangle with the `TangleLayer`: -This consumer processes job results and submits them back to the Tangle EVM contract. +This consumer processes job results and submits them back to the Tangle contract. For more details on consumers, see the [Consumers documentation](/developers/blueprint-runner/consumers). diff --git a/pages/developers/blueprint-runner/consumers.mdx b/pages/developers/blueprint-runner/consumers.mdx index 75d94734..be3cbb5f 100644 --- a/pages/developers/blueprint-runner/consumers.mdx +++ b/pages/developers/blueprint-runner/consumers.mdx @@ -35,20 +35,20 @@ Consumers are typically configured in the `main.rs` file of your Blueprint binar ### Basic Consumer Setup -First, you define the consumer you want to use. For example, a `TangleEvmConsumer` that submits job results back to the Tangle EVM contracts. After which, you pass the consumer to the Blueprint Runner's builder. +First, you define the consumer you want to use. For example, a `TangleConsumer` that submits job results back to the Tangle contracts. After which, you pass the consumer to the Blueprint Runner's builder. ```rust let env = BlueprintEnvironment::load()?; -let tangle_client = env.tangle_evm_client().await?; +let tangle_client = env.tangle_client().await?; let service_id = env .protocol_settings - .tangle_evm()? + .tangle()? .service_id .ok_or_else(|| blueprint_sdk::Error::Other("No service ID configured".to_string()))?; -let tangle_producer = TangleEvmProducer::new(tangle_client.clone(), service_id); -let tangle_consumer = TangleEvmConsumer::new(tangle_client.clone()); -let tangle_config = TangleEvmConfig::default(); +let tangle_producer = TangleProducer::new(tangle_client.clone(), service_id); +let tangle_consumer = TangleConsumer::new(tangle_client.clone()); +let tangle_config = TangleConfig::default(); BlueprintRunner::builder(tangle_config, env) .router(router) // Assuming your router is already defined @@ -62,15 +62,15 @@ BlueprintRunner::builder(tangle_config, env) Blueprint Runners can utilize various types of consumers depending on the requirements: -### Tangle EVM Consumer +### Tangle Consumer -A Tangle EVM Consumer is a consumer that submits job results to the Tangle Jobs contract. +A Tangle Consumer is a consumer that submits job results to the Tangle Jobs contract. ### Generic EVM Consumer diff --git a/pages/developers/blueprint-runner/introduction.mdx b/pages/developers/blueprint-runner/introduction.mdx index 01c7de48..d50f7b39 100644 --- a/pages/developers/blueprint-runner/introduction.mdx +++ b/pages/developers/blueprint-runner/introduction.mdx @@ -29,6 +29,21 @@ Blueprint Runners are the core orchestration components that execute Tangle Blue description: "Understand how producers capture and process events for your Blueprint.", link: "/developers/blueprint-runner/producers" }, + { + title: "Job Triggers", + description: "A map of cron, on-chain events, webhooks, x402, and custom producers.", + link: "/developers/blueprint-runner/job-triggers" + }, + { + title: "Webhooks", + description: "Trigger jobs from external HTTP webhooks.", + link: "/developers/blueprint-runner/webhooks" + }, + { + title: "x402 Payments", + description: "Accept paid HTTP job calls via x402 settlement.", + link: "/developers/blueprint-runner/x402" + }, { title: "Consumers", description: "Learn how consumers handle job results in your Blueprint Runner.", diff --git a/pages/developers/blueprint-runner/job-triggers.mdx b/pages/developers/blueprint-runner/job-triggers.mdx new file mode 100644 index 00000000..d0e1cfd3 --- /dev/null +++ b/pages/developers/blueprint-runner/job-triggers.mdx @@ -0,0 +1,107 @@ +--- +title: Job Triggers +description: A map of the common ways a Blueprint Runner receives work (on-chain events, cron, webhooks, x402, and custom producers). +--- + +import GithubFileReaderDisplay from "/components/GithubFileReaderDisplay"; + +# Job Triggers + +In Blueprint Runner terms, most "triggers" are just ways to produce a `JobCall`. + +If something can emit a stream of `JobCall`s, the runner can route them to job handlers. + +This page is a guide to the common trigger patterns and where they live in the SDK. + +## Mental Model + +- A `Producer` is a `Stream>`. +- A `JobCall` is the unit the router dispatches. +- Some trigger types are pure producers (on-chain, cron). +- Some trigger types are a gateway plus a producer: + - the gateway runs an HTTP server as a background service + - the producer converts verified inbound requests into `JobCall`s + +## On-Chain Event Triggers (Tangle) + +Use this when you want jobs to run in response to Tangle protocol events (for example job submissions). + +The built-in `TangleProducer` listens for on-chain job submission events and yields `JobCall`s: + + + +Docs: + +- `/developers/blueprint-runner/producers` + +## Polling Triggers (EVM Polling) + +If the event source is not an indexed event stream, polling can still produce `JobCall`s at your own cadence: + + + +Docs: + +- `/developers/blueprint-runner/producers` + +## Cron Triggers (Scheduled Jobs) + +For scheduled work, use a cron producer that emits `JobCall`s on a schedule: + + + +Docs: + +- `/developers/blueprint-runner/producers` + +## Webhooks (HTTP Ingress) + +If an external system should trigger a job by calling an HTTP endpoint, use the webhook gateway: + +- Gateway: verifies auth, accepts the request, then injects an event +- Producer: turns verified events into `JobCall`s + +Docs: + +- `/developers/blueprint-runner/webhooks` + +## x402 (Paid HTTP Job Calls) + +If you want HTTP job calls that require payment (stablecoins on EVM chains, verified via an x402 facilitator), use the +x402 gateway: + +- Gateway: advertises payment requirements, verifies and settles payment, then injects a verified payment +- Producer: turns verified payments into `JobCall`s + +Docs: + +- `/developers/blueprint-runner/x402` + +## Custom Triggers (Bring Your Own Producer) + +If none of the built-ins fit, implement your own producer. The only hard requirement is that your producer yields +`JobCall`s that your router understands. + +Typical patterns: + +- poll an external API and emit a `JobCall` when a condition is met +- consume a message queue (Kafka, NATS, SQS) and convert messages into `JobCall`s +- subscribe to a websocket feed and emit `JobCall`s from inbound frames + +If you also need to run a long-lived side task (HTTP server, queue consumer, subscription reconnection loop), you can +combine a `BackgroundService` with a channel-based producer, the same pattern used by the webhooks and x402 gateways. diff --git a/pages/developers/blueprint-runner/jobs.mdx b/pages/developers/blueprint-runner/jobs.mdx index b2184bb6..147cad65 100644 --- a/pages/developers/blueprint-runner/jobs.mdx +++ b/pages/developers/blueprint-runner/jobs.mdx @@ -44,8 +44,8 @@ In this example: - `XSQUARE_JOB_ID` is a constant that uniquely identifies the job - `square` is the function that implements the job's logic -- The job takes a single ABI-encoded input parameter `x` extracted by `TangleEvmArg` -- The job returns a `TangleEvmResult`, which the runner ABI-encodes for submission +- The job takes a single ABI-encoded input parameter `x` extracted by `TangleArg` +- The job returns a `TangleResult`, which the runner ABI-encodes for submission ## Job Context diff --git a/pages/developers/blueprint-runner/producers.mdx b/pages/developers/blueprint-runner/producers.mdx index 34e5c8f4..064dab2c 100644 --- a/pages/developers/blueprint-runner/producers.mdx +++ b/pages/developers/blueprint-runner/producers.mdx @@ -25,18 +25,18 @@ Producers are typically configured in the `main.rs` file of your Blueprint binar ### Basic Producer Setup -First, you define the producer you want to use. For example, a `TangleEvmProducer` that listens for `JobSubmitted` events on Tangle EVM. After which, you pass the producer to the Blueprint Runner's builder. +First, you define the producer you want to use. For example, a `TangleProducer` that listens for `JobSubmitted` events on Tangle. After which, you pass the producer to the Blueprint Runner's builder. ```rust let env = BlueprintEnvironment::load()?; -let tangle_client = env.tangle_evm_client().await?; +let tangle_client = env.tangle_client().await?; let service_id = env .protocol_settings - .tangle_evm()? + .tangle()? .service_id .ok_or_else(|| blueprint_sdk::Error::Other("No service ID configured".to_string()))?; -let tangle_producer = TangleEvmProducer::new(tangle_client.clone(), service_id); -let tangle_config = TangleEvmConfig::default(); +let tangle_producer = TangleProducer::new(tangle_client.clone(), service_id); +let tangle_config = TangleConfig::default(); BlueprintRunner::builder(tangle_config, env) .router(router) // Assuming your router is already defined @@ -55,13 +55,13 @@ These producers listen for events from a blockchain, such as smart contract even There are currently two built-in blockchain producers: -#### Tangle EVM Producer +#### Tangle Producer #### EVM Polling Producer diff --git a/pages/developers/blueprint-runner/routers.mdx b/pages/developers/blueprint-runner/routers.mdx index 09aa19f5..fbf1bad2 100644 --- a/pages/developers/blueprint-runner/routers.mdx +++ b/pages/developers/blueprint-runner/routers.mdx @@ -55,9 +55,9 @@ Below is a real example from our Incredible Squaring Blueprint Example: Layers are used to filter job calls based on certain criteria. There are two places layers can be used: 1. A specific Route: - - A job can be given a layer. This can be seen in the above code example, where the job is wrapped in the `TangleEvmLayer`. This adds Tangle EVM metadata to job results for the consumer. + - A job can be given a layer. This can be seen in the above code example, where the job is wrapped in the `TangleLayer`. This adds Tangle metadata to job results for the consumer. 2. A whole Router: - - A layer can be used to filter job calls based on criteria you control (for example, metadata from Tangle EVM extractors). + - A layer can be used to filter job calls based on criteria you control (for example, metadata from Tangle extractors). ## Integration with Other Components diff --git a/pages/developers/blueprint-runner/webhooks.mdx b/pages/developers/blueprint-runner/webhooks.mdx new file mode 100644 index 00000000..3ea1788c --- /dev/null +++ b/pages/developers/blueprint-runner/webhooks.mdx @@ -0,0 +1,91 @@ +--- +title: Webhooks Gateway +description: Trigger Blueprint jobs from external HTTP webhooks using WebhookGateway (axum) and WebhookProducer. +--- + +import GithubFileReaderDisplay from "/components/GithubFileReaderDisplay"; + +# Webhooks Gateway + +SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/v2/crates/webhooks + +The webhooks feature is an optional HTTP ingress path for a Blueprint Runner. It lets you expose one or more HTTP +endpoints that: + +- verify an auth policy (none, bearer, HMAC-SHA256, or API key) +- accept an arbitrary request body +- inject a `JobCall` into the runner for a configured `job_id` + +This is useful when your blueprint needs to react to external events that are not natively on-chain. + +## When to Use It + +- TradingView alerts, exchange notifications, monitoring events +- external schedulers or orchestrators that should trigger a job handler +- bridging legacy systems into a service instance without writing a custom producer + +## How It Fits In the Runner + +`WebhookGateway` runs as a `BackgroundService` (an `axum` server), and `WebhookProducer` is the paired producer that +turns verified webhook requests into `JobCall`s. + +The gateway stamps each `JobCall` with metadata: + +- `X-TANGLE-SERVICE-ID` and `X-TANGLE-CALL-ID` (synthetic, for correlation) +- `X-WEBHOOK-PATH` and `X-WEBHOOK-NAME` (if configured) + +Quick start (from the crate docs): + + + +## Enabling It (Blueprint SDK) + +If you are using `blueprint-sdk`, enable the feature flag: + +```toml +[dependencies] +blueprint-sdk = { version = "*", features = ["webhooks"] } +``` + +You can also depend on `blueprint-webhooks` directly if you do not want the full SDK re-export surface. + +## Configuration (TOML) + +Webhook endpoints are configured in TOML. Each endpoint maps a URL path to a `job_id` and an auth mode. + + + +Notes: + +- `path` must start with `/`. +- For `bearer`, `hmac-sha256`, and `api-key`, `secret` is required. +- `secret` supports `env:VAR_NAME` expansion. +- `service_id` is set at runtime, not from TOML. If it is left as `0`, downstream components that rely on a service ID + will not behave as expected. + +## Auth Modes + +Supported auth modes are: + +- `none`: accepts any request. +- `bearer`: requires `Authorization: Bearer `. +- `hmac-sha256`: checks a hex signature over the raw body. The gateway accepts `X-Signature-256`, + `X-Hub-Signature-256`, or `X-Webhook-Signature`. Values may be prefixed with `sha256=`. +- `api-key`: checks a static key in a header (default `X-API-Key`, configurable via `api_key_header`). + +## Operational Notes + +- Health endpoint: `GET /webhooks/health` returns `ok`. +- Each configured webhook endpoint responds `202 Accepted` on success and returns a `call_id`. +- Treat webhook ingress as untrusted input. Validate and parse the request body inside the job handler. +- Prefer `hmac-sha256` or `bearer` when receiving webhooks from the public internet. diff --git a/pages/developers/blueprint-runner/x402.mdx b/pages/developers/blueprint-runner/x402.mdx new file mode 100644 index 00000000..0df5670a --- /dev/null +++ b/pages/developers/blueprint-runner/x402.mdx @@ -0,0 +1,100 @@ +--- +title: x402 Payment Gateway +description: Accept x402 payments over HTTP and translate them into paid job executions inside a Blueprint Runner. +--- + +import GithubFileReaderDisplay from "/components/GithubFileReaderDisplay"; + +# x402 Payment Gateway + +SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/v2/crates/x402 + +x402 is an optional, off-chain payment ingress path for job execution. It exposes HTTP endpoints that require a valid +x402 payment (typically stablecoins on an EVM chain) and then injects a `JobCall` into the Blueprint Runner after the +payment is verified and settled by an x402 facilitator. + +This is useful when you want a service to accept payments from clients on EVM chains without requiring the client to +submit on-chain Tangle transactions for each job. + +## How It Fits In the Runner + +`X402Gateway` runs as a `BackgroundService` and `X402Producer` is the paired producer that converts verified payments +into `JobCall`s. + +Quick start (from the crate docs): + + + +Each x402-originated `JobCall` includes metadata for correlation and accounting: + +- `X-X402-ORIGIN` and `X-X402-QUOTE-DIGEST` +- `X-X402-PAYMENT-NETWORK` and `X-X402-PAYMENT-TOKEN` +- `X-TANGLE-SERVICE-ID` and `X-TANGLE-CALL-ID` (synthetic, for correlation) + +## Enabling It (Blueprint SDK) + +If you are using `blueprint-sdk`, enable the feature flag: + +```toml +[dependencies] +blueprint-sdk = { version = "*", features = ["x402"] } +``` + +You can also depend on `blueprint-x402` directly. + +## Configuration (TOML) + +The operator configures: + +- where the gateway listens (`bind_address`) +- which facilitator to use (`facilitator_url`) +- which tokens and chains are accepted (`accepted_tokens`) +- conversion rates from wei-denominated job prices into token amounts (`rate_per_native_unit`, plus optional `markup_bps`) + + + +## Job Pricing Input + +The x402 gateway needs a per-job price map in wei: + +- key: `(service_id, job_index)` +- value: `price_wei` + +This is the same shape as the pricing engine job pricing config, and it is intentionally explicit. If a job is not in +the map, the gateway returns `404` for that job. + +## HTTP Endpoints + +The gateway exposes: + +- `GET /x402/health`: returns `ok`. +- `GET /x402/jobs/{service_id}/{job_index}/price`: discovery endpoint that returns the wei price and settlement options + (no payment required). +- `POST /x402/jobs/{service_id}/{job_index}`: paid job execution. The x402 middleware returns `402` with payment + requirements if no valid payment is provided. After payment settles, the gateway returns `202 Accepted` and injects a + `JobCall` into the runner. + +## Relationship to RFQ and the Pricing Engine + +Tangle’s on-chain RFQ path is `submitJobFromQuote`. Separately, operators can expose x402 as an off-chain settlement +path. + +The pricing engine proto includes optional x402 fields (`settlement_options`, `x402_endpoint`) in `GetJobPriceResponse`. +At time of writing, enabling those fields requires constructing `PricingEngineService` programmatically with +`with_x402_settlement`, since the `pricing-engine-server` binary does not expose x402 flags yet. + +## Operational Notes + +- Keep `facilitator_url` pinned to a trusted HTTPS endpoint. +- Keep conversion rates current. Stale `rate_per_native_unit` values create user-facing price surprises. +- Treat the HTTP body as untrusted input and validate it inside the job handler. diff --git a/pages/developers/blueprint-sdk.mdx b/pages/developers/blueprint-sdk.mdx index 3510a61b..6518d21f 100644 --- a/pages/developers/blueprint-sdk.mdx +++ b/pages/developers/blueprint-sdk.mdx @@ -15,6 +15,7 @@ It includes: - The **[Blueprint Runner](https://github.com/tangle-network/blueprint/tree/v2/crates/runner)** (router + producers + consumers + background services) - Typed **[contexts](https://github.com/tangle-network/blueprint/tree/v2/crates/contexts)** (keystore, EVM provider, Tangle EVM client) - The [`cargo-tangle` CLI](https://github.com/tangle-network/blueprint/tree/v2/cli) for creating, preregistering, and running blueprints +- Optional gateways for HTTP ingress and settlement (webhooks, x402) **Source of truth repos** @@ -71,6 +72,8 @@ The CLI exposes these as shared flags: { title: "Jobs", href: "/developers/blueprint-runner/jobs", description: "Define job handlers" }, { title: "Routers", href: "/developers/blueprint-runner/routers", description: "Route job calls to handlers" }, { title: "Producers", href: "/developers/blueprint-runner/producers", description: "Convert events to job calls" }, + { title: "Webhooks", href: "/developers/blueprint-runner/webhooks", description: "Trigger jobs from external HTTP" }, + { title: "x402 Payments", href: "/developers/blueprint-runner/x402", description: "Paid job calls via x402 settlement" }, { title: "Consumers", href: "/developers/blueprint-runner/consumers", description: "Submit results back to chain" }, ], }, diff --git a/pages/developers/blueprints/_meta.ts b/pages/developers/blueprints/_meta.ts index 8017362e..1756b56d 100644 --- a/pages/developers/blueprints/_meta.ts +++ b/pages/developers/blueprints/_meta.ts @@ -3,7 +3,8 @@ import { Meta } from "nextra"; const meta: Meta = { introduction: "Introduction", "use-cases": "Use Cases", - "pricing-engine": "Pricing", + "pricing-and-payments": "Pricing & Payments", + "pricing-engine": "Pricing Engine", manager: "Blueprint Manager", }; diff --git a/pages/developers/blueprints/pricing-and-payments.mdx b/pages/developers/blueprints/pricing-and-payments.mdx new file mode 100644 index 00000000..c952d353 --- /dev/null +++ b/pages/developers/blueprints/pricing-and-payments.mdx @@ -0,0 +1,113 @@ +--- +title: Pricing and Payments +description: Protocol-level pricing models (PayOnce, Subscription, EventDriven), per-job rates, and RFQ job/service quotes. +--- + +import GithubFileReaderDisplay from "/components/GithubFileReaderDisplay"; + +# Pricing and Payments + +This page describes the protocol-level pricing surface for Tangle blueprints: which pricing models exist, when to use +them, and how fixed rates vs RFQ (request-for-quote) work for both services and jobs. + +If you are looking for the operator-side gRPC daemon that generates EIP-712 quotes, see: + +- `/developers/blueprints/pricing-engine` + +## Source Of Truth + +The most comprehensive, protocol-accurate reference lives in `tnt-core`: + + + +## Pricing Models (BlueprintConfig) + +Every blueprint declares a `PricingModel` at registration time. This cannot be changed after registration. + +- `PayOnce`: user pays up front when creating a service. +- `Subscription`: service owner funds escrow; anyone can trigger periodic billing. +- `EventDriven`: job submitter pays per job (with optional per-job overrides). + +## CLI and Tooling + +The protocol supports multiple pricing paths, but the CLI does not cover every one yet. + +Supported CLI flows: + +- Service lifecycle request and approval flow: `cargo tangle blueprint service request`, then `service approve` (operator) and related commands. See `/developers/cli/tangle`. +- Standard job submission: `cargo tangle blueprint jobs submit` and `jobs watch`. This uses on-chain pricing for the service and blueprint (fixed rates, or whatever the blueprint config resolves to at submission time). + +Flows that typically require custom code today: + +- Per-job RFQ submission (`submitJobFromQuote`): you need to request signed quotes off-chain, then submit the job with the quotes. +- Service RFQ creation (`createServiceFromQuotes` / `extendServiceFromQuotes`): you need to request signed service quotes off-chain, then create or extend the service using those quotes. + +For Rust clients, `TangleClient` supports RFQ job submission: + + + +## Fixed Pricing (EventDriven: Per-Job Rates) + +For `EventDriven`, price resolution is: + +1. Per-job override (set by blueprint owner) for `(blueprintId, jobIndex)` +2. Fallback to `BlueprintConfig.eventRate` + +This is the simplest path for predictable job costs. + +If you need per-job overrides, plan for an operator or owner tool that calls `setJobEventRates` on-chain. Many teams do this via a Foundry script or a small Rust admin binary. + +## Job RFQ (submitJobFromQuote) + +Use Job RFQ when the price should be negotiated per request (LLM model selection, variable compute, discounts, etc.). + +High-level flow: + +1. User requests a per-job quote from one or more operators (off-chain). +2. Operators respond with an EIP-712 signed `JobQuoteDetails { serviceId, jobIndex, price, timestamp, expiry }`. +3. User submits the job on-chain with the signed quote(s) via `submitJobFromQuote`. + +Key properties: + +- `msg.value` must equal `sum(quote.price)` across quotes. +- Quotes are replay-protected and expire (protocol also enforces `maxQuoteAge`). +- Only quoted operators can submit results for RFQ jobs. + +## Off-Chain Settlement (x402, optional) + +Some services want an HTTP-first, stablecoin settlement path for paid job execution. The Blueprint SDK includes an +optional x402 gateway that can: + +1. advertise payment requirements per job +2. accept and verify x402 payments via a facilitator +3. inject the paid request as a `JobCall` into the Blueprint Runner + +This is separate from on-chain payment collection (`submitJob` / `submitJobFromQuote`), and it is implemented as an +operator-run gateway. See: + +- `/developers/blueprint-runner/x402` + +## Service RFQ (createServiceFromQuotes / extendServiceFromQuotes) + +Service RFQ lets a user create a service instantly using operator quotes: + +1. User requests service quotes from operators for `(blueprintId, ttlBlocks, security requirements)`. +2. Operators sign EIP-712 `QuoteDetails { blueprintId, ttlBlocks, totalCost, timestamp, expiry, ... }`. +3. User calls `createServiceFromQuotes(...)` (or `extendServiceFromQuotes(...)`) with quotes and payment. + +This is separate from the request and approval service lifecycle flow that the CLI exposes under `cargo tangle blueprint service`. + +## Payment Tokens and Escrow (Subscription) + +For `Subscription`, a service owner funds escrow and billing is triggered on an interval. If escrow is insufficient, +billing reverts until it is funded again. See the `tnt-core` pricing guide for exact functions and semantics. diff --git a/pages/developers/blueprints/pricing-engine.mdx b/pages/developers/blueprints/pricing-engine.mdx index 8f427f82..ac7f430d 100644 --- a/pages/developers/blueprints/pricing-engine.mdx +++ b/pages/developers/blueprints/pricing-engine.mdx @@ -1,48 +1,66 @@ --- -title: Blueprint Pricing +title: Pricing Engine (RFQ Server) --- -# Blueprint Pricing +import GithubFileReaderDisplay from "/components/GithubFileReaderDisplay"; -Tangle v2 supports fixed-price and quote-based pricing. The pricing engine is the operator-side RFQ server that produces -signed quotes for instant service creation. +# Pricing Engine (RFQ Server) + +Tangle supports fixed pricing and RFQ (request-for-quote). The pricing engine is the operator-side gRPC server that +generates EIP-712 signed quotes that users submit on-chain. + +Protocol overview (pricing models, fixed per-job rates, RFQ semantics): + +- `/developers/blueprints/pricing-and-payments` ## When to Use the Pricing Engine -- Use it when your blueprint expects RFQ quotes and you want customers to create services immediately with signed - operator quotes. -- If your blueprint uses standard pay-once or subscription pricing, you can skip the pricing engine. +- Use it when you want operators to answer RFQs off-chain (service creation quotes and/or per-job quotes). +- If your blueprint only uses fixed pricing (e.g. per-job rates via `setJobEventRates`), you can skip it. ## End-to-End Flow -1. **Operator runs `pricing-engine-server`** with a pricing config and the Tangle RPC + contract addresses. -2. **Customer requests quotes** over gRPC (`GetPrice`) with TTL, proof-of-work, and security requirements. -3. **Operator returns a signed quote** (ECDSA signature over ABI-encoded `QuoteDetails`). -4. **Customer creates a service** by calling - [`ITangleServices.createServiceFromQuotes`](/developers/api/reference/ITangleServices) with the selected quotes. - Use `extendServiceFromQuotes` to add TTL later. - -## Quote Format - -The gRPC schema matches `ITangle.SignedQuote`. The `QuoteDetails` payload looks like: - -```proto -message QuoteDetails { - uint64 blueprint_id = 1; - uint64 ttl_blocks = 2; - double total_cost_rate = 3; - uint64 timestamp = 4; - uint64 expiry = 5; - repeated ResourcePricing resources = 6; - repeated AssetSecurityCommitment security_commitments = 7; -} -``` +The pricing engine supports two RFQ modes: + +1. Service creation quotes (`GetPrice`) to use with `createServiceFromQuotes` / `extendServiceFromQuotes` +2. Per-job quotes (`GetJobPrice`) to use with `submitJobFromQuote` + +`GetJobPriceResponse` also includes optional x402 settlement fields (`settlement_options`, `x402_endpoint`). Clients that +do not use x402 can ignore them. + +See the upstream README for exact semantics, flags, and configuration formats: + + -## Pricing Configuration +## Operator Configuration (TOML) -Pricing rates live in a TOML file. A default section applies to every blueprint, and you can override rates per -blueprint ID. The SDK ships a sample at -`crates/pricing-engine/config/default_pricing.toml`. +These are the files operators typically tune: + + + + + + ## Runbook (Operator) @@ -71,16 +89,27 @@ Important environment variables: - `GetPrice` uses proof-of-work to rate-limit RPC abuse. - Quotes include TTL + expiry and are signed with the operator ECDSA key to prevent replay. +## x402 Settlement Options (Optional) + +The pricing engine has a programmatic integration point that can attach x402 settlement options to every per-job quote. +This is intended to pair with the SDK’s x402 gateway. + +At time of writing, the `pricing-engine-server` binary does not expose CLI flags for x402 settlement. If you want the +gRPC server to return x402 settlement options, you need to construct the pricing engine service in code using +`PricingEngineService::with_x402_settlement`, and run an x402 gateway at the returned `x402_endpoint`. + ## Source of Truth - Pricing engine README: https://github.com/tangle-network/blueprint/blob/v2/crates/pricing-engine/README.md - Pricing proto: https://github.com/tangle-network/blueprint/blob/v2/crates/pricing-engine/proto/pricing.proto -1. **Get Multiple Quotes**: Always request quotes from all registered operators to compare prices -2. **Verify All Signatures**: Always verify the signature of each quote before using it -3. **Check Expiry Times**: Ensure quotes haven't expired before submitting them to the blockchain -4. **Include Complete Security Requirements**: Specify all necessary security parameters in your requests -5. **Handle Errors Gracefully**: Implement proper error handling for failed quote requests -6. **Keep Quotes Intact**: Never modify quote details after receiving them -7. **Use Fresh Proof-of-Work**: Generate a new proof-of-work for each request -8. **Expect Price Variation**: Don't assume all operators will provide the same price +## Best Practices + +1. Get multiple quotes from multiple operators and compare them. +2. Verify signatures before using quotes on-chain. +3. Check quote expiry before submission. +4. Include complete security requirements in RFQ requests, otherwise quotes may not be usable for your desired service. +5. Handle request failures and timeouts explicitly. +6. Keep quote details intact. Never modify quote payloads after they are signed. +7. Generate fresh proof-of-work per request if your deployment uses PoW gating. +8. Expect price variation across operators. diff --git a/pages/developers/p2p-networking/usage.mdx b/pages/developers/p2p-networking/usage.mdx index 1d5539d4..bb53ab97 100644 --- a/pages/developers/p2p-networking/usage.mdx +++ b/pages/developers/p2p-networking/usage.mdx @@ -77,7 +77,7 @@ Store the `NetworkServiceHandle` inside your context so job handlers and backgro ```rust use blueprint_sdk::crypto::k256::K256Ecdsa; use blueprint_sdk::networking::NetworkServiceHandle; -use blueprint_sdk::{Router, tangle_evm::TangleEvmLayer}; +use blueprint_sdk::{Router, tangle::TangleLayer}; #[derive(Clone)] struct P2pContext { @@ -89,7 +89,7 @@ let context = P2pContext { }; let router = Router::new() - .route(MY_JOB_ID, my_job.layer(TangleEvmLayer)) + .route(MY_JOB_ID, my_job.layer(TangleLayer)) .with_context(context); ``` diff --git a/pages/developers/system-architecture/overview.mdx b/pages/developers/system-architecture/overview.mdx index 491e46cf..1d74651c 100644 --- a/pages/developers/system-architecture/overview.mdx +++ b/pages/developers/system-architecture/overview.mdx @@ -47,11 +47,11 @@ Tangle is an EVM protocol for instantiating and operating **services (“bluepri ### Off-Chain ([Blueprint SDK](https://github.com/tangle-network/blueprint/tree/v2)) -| Component | Responsibility | Code | -| ---------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -| Manager | Loads services from chain, selects runtime sources, runs blueprints | https://github.com/tangle-network/blueprint/tree/v2/crates/manager | -| Tangle EVM contexts | Provides typed clients + operator identity + env | https://github.com/tangle-network/blueprint/blob/v2/crates/contexts/src/tangle_evm.rs | -| Tangle EVM producer/consumer | EVM event ingestion + result submission helpers | https://github.com/tangle-network/blueprint/tree/v2/crates/tangle-evm-extra/src | +| Component | Responsibility | Code | +| ------------------------ | ------------------------------------------------------------------- | --------------------------------------------------------------------------------- | +| Manager | Loads services from chain, selects runtime sources, runs blueprints | https://github.com/tangle-network/blueprint/tree/v2/crates/manager | +| Tangle contexts | Provides typed clients + operator identity + env | https://github.com/tangle-network/blueprint/blob/v2/crates/contexts/src/tangle.rs | +| Tangle producer/consumer | Job ingestion + result submission helpers | https://github.com/tangle-network/blueprint/tree/v2/crates/tangle-extra/src | ## The Entrypoint Contract (Composition) diff --git a/pages/infrastructure/_meta.ts b/pages/infrastructure/_meta.ts index c8ea9c48..54fd3fe1 100644 --- a/pages/infrastructure/_meta.ts +++ b/pages/infrastructure/_meta.ts @@ -5,6 +5,7 @@ const meta: Meta = { architecture: "Architecture", orchestration: "Orchestration", sandboxing: "Sandboxing and Safety", + "protocol-deployment": "Protocol Deployment", }; export default meta; diff --git a/pages/infrastructure/protocol-deployment.mdx b/pages/infrastructure/protocol-deployment.mdx new file mode 100644 index 00000000..76f6796f --- /dev/null +++ b/pages/infrastructure/protocol-deployment.mdx @@ -0,0 +1,44 @@ +--- +title: Protocol Deployment (tnt-core) +description: How protocol deployments are orchestrated in tnt-core (FullDeploy, manifests, and slashing wiring). +--- + +import GithubFileReaderDisplay from "/components/GithubFileReaderDisplay"; + +# Protocol Deployment (tnt-core) + +This page is for protocol and infrastructure engineers deploying the Tangle EVM contracts. Blueprint operators do not +need these steps for day to day service operation. + +The source of truth for deployment is the `tnt-core` repo, which uses Foundry scripts and writes manifest JSON outputs +for downstream tooling. + +## Source of Truth + + + + + +## What To Document in Runbooks + +If you operate a production environment, keep these items in your internal runbook so deployments stay reproducible: + +- the `FULL_DEPLOY_CONFIG` JSON you used (and any env var overrides) +- the manifest output path and the produced manifest JSON +- role handoff targets (timelock, multisig, treasury) and whether bootstrap roles were revoked +- any cross-chain slashing wiring (Hyperlane or LayerZero) and the connector and receiver manifests + +## Related Docs + +- Protocol architecture overview: `/developers/protocol-architecture` +- Network parameters and contract addresses: `/network/network-parameters` diff --git a/pages/operators/pricing/overview.mdx b/pages/operators/pricing/overview.mdx index 9df6221b..eda3021e 100644 --- a/pages/operators/pricing/overview.mdx +++ b/pages/operators/pricing/overview.mdx @@ -6,95 +6,65 @@ title: Blueprint Pricing SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/v2/crates/pricing-engine -Operator preferences interface (GitHub): https://github.com/tangle-network/tnt-core/blob/main/src/interfaces/ITangleOperators.sol +Operator preferences interface (GitHub): https://github.com/tangle-network/tnt-core/blob/v2/src/interfaces/ITangleOperators.sol -As a blueprint operator, you'll need to set up pricing for your services to receive fair compensation for the resources you provide. This guide explains how pricing works in the Tangle Network and how to configure it properly. +As an operator, you get paid based on how a blueprint is configured to charge. Some pricing is fixed on-chain (no quote +service required). Other flows require operators to serve signed quotes off-chain (RFQ). ## Prerequisites - Basic understanding of Tangle Network operations -- Familiarity with running the Blueprint Manager runtime -- Knowledge of blueprint concepts and service lifecycles +- Familiarity with the Blueprint Manager runtime +- Knowledge of blueprint service lifecycles -## How Blueprint Pricing Works +## Pricing Models (What You Need to Run) -The pricing process follows these steps: +Every blueprint declares a pricing model at registration time. As an operator, your responsibilities depend on the model. -1. **Registration**: When you register as an operator for a blueprint, you provide your pricing service address in your preferences - - **Note**: If your RPC server address changes, update it on-chain via `updateOperatorPreferences` on the `Tangle` contract (see `ITangleOperators`) -2. **Quote Requests**: Users request price quotes from registered operators like you -3. **Quote Generation**: Your service calculates prices based on resource requirements, creates security commitments, and signs quotes -4. **Operator Selection**: Users select operators based on price and other factors -5. **Service Execution**: Once selected, you'll begin execution of the blueprint and receive payment +Reference: `/developers/blueprints/pricing-and-payments` -## Setting Up Your Pricing Service +### Fixed On-Chain Pricing (No RFQ) -Your pricing service needs to be available via gRPC for users to request quotes. Here's how to configure it: +In most deployments these flows do not require you to run a quote server: -### Pricing Configuration +- `Subscription`: the service is billed on-chain at a fixed `subscriptionRate` each interval (escrow funded by the owner). +- `EventDriven` with fixed per-job rates: the job submitter pays a fixed amount at `submitJob()`, resolved from the + blueprint config and optional per-job overrides. -Create a TOML configuration file with your pricing structure. The file should include both default pricing for all blueprints and specific pricing for particular blueprints: +In these models, you still need normal operational hygiene (uptime, heartbeats, QoS, and correct consumer behavior), but +you do not need to publish off-chain quotes to get paid. -```toml -# Default pricing for all blueprints -[default] -resources = [ - { kind = "CPU", count = 1, price_per_unit_rate = 0.001 }, - { kind = "MemoryMB", count = 1024, price_per_unit_rate = 0.00005 }, - { kind = "StorageMB", count = 1024, price_per_unit_rate = 0.00002 }, - { kind = "NetworkEgressMB", count = 1024, price_per_unit_rate = 0.00003 }, - { kind = "NetworkIngressMB", count = 1024, price_per_unit_rate = 0.00001 }, - { kind = "GPU", count = 1, price_per_unit_rate = 0.005 } -] +### RFQ Pricing (You Must Serve Quotes) -# Blueprint-specific pricing (overrides default) -[123] # Blueprint ID -resources = [ - { kind = "CPU", count = 1, price_per_unit_rate = 0.0012 }, - { kind = "MemoryMB", count = 2048, price_per_unit_rate = 0.00006 }, - { kind = "StorageMB", count = 1024, price_per_unit_rate = 0.00002 }, - { kind = "NetworkEgressMB", count = 1024, price_per_unit_rate = 0.00003 }, - { kind = "NetworkIngressMB", count = 1024, price_per_unit_rate = 0.00001 }, - { kind = "GPU", count = 1, price_per_unit_rate = 0.005 } -] -``` +These flows require operators to generate and sign EIP-712 quotes off-chain: -Each resource type defines: +- `PayOnce`: users create a service using `createServiceFromQuotes(...)`. +- Job RFQ: users submit jobs using `submitJobFromQuote(...)`. -- `kind`: The resource type (CPU, MemoryMB, StorageMB, etc.) -- `count`: The baseline quantity for the resource -- `price_per_unit_rate`: The price per unit in USD with decimal precision, where it is generally the price per block for the resource +To participate in RFQ, you need: -### How Prices Are Calculated +- a quote serving endpoint (typically the `pricing-engine` gRPC server) +- your on-chain operator preferences updated with that endpoint -The formula used to calculate blueprint execution pricing is: +If your quote server address changes, update it on-chain via `updateOperatorPreferences` (see `ITangleOperators`). -``` -Price = Resource Cost × Duration Factor × Security Factor -``` +## Running the Pricing Engine (Recommended) -Where: +The simplest path is to run the `pricing-engine-server` binary and configure: -- **Resource Cost** = resource_count × price_per_unit_rate -- **Duration Factor** = time_blocks × BLOCK_TIME -- **Security Factor** = Factor based on security commitment parameters +- operator identity and quote signing key (`operator.toml`) +- service quote pricing tables (resource pricing TOML) +- job quote pricing tables (job pricing TOML) -## Security Commitments +Developer and operator details live here: -When users request your services, they include security requirements that specify what percentage of assets you need to secure. Your pricing service needs to respond with your commitment: +- `/developers/blueprints/pricing-engine` -- **Exposure Percentage**: The percentage of assets you guarantee to secure (between the user's minimum and maximum requirements) -- **Asset Types**: Native (address(0)) or ERC20 (token address) +## Optional: x402 Settlement (Paid HTTP Jobs) -This commitment will be included with your signed quote. The commitment used for the quote is automatically the minimum exposure percentage specified in the user's security requirements. +If you want an HTTP-first paid job interface (stablecoin settlement on EVM chains), you can run the SDK’s x402 gateway. +This is separate from on-chain payment collection and is operated as a Blueprint Runner background service. -## Quote Security Considerations +Reference: -### Quote Signature - -- To ensure the validity of your quotes, your quotes are automatically signed. Users then verify the signature included in an Operator's quote when they receive it. This ensures a user is getting genuine quotes from you and other operators. - -### Protection Against Abuse - -- **Proof-of-Work Verification**: Users provide proof-of-work with their requests, defending against Denial-of-Service (DoS) attacks -- **Quote Expiry**: Quotes include an expiry time (typically 10-15 minutes) to prevent stale quotes +- `/developers/blueprint-runner/x402` diff --git a/pages/operators/quality-of-service.mdx b/pages/operators/quality-of-service.mdx index 2f93100f..25001f47 100644 --- a/pages/operators/quality-of-service.mdx +++ b/pages/operators/quality-of-service.mdx @@ -16,11 +16,16 @@ QoS uses Prometheus-compatible metrics by default, with optional Grafana and Lok | Grafana UI | `http://:3000` | Only when configured or managed by QoS. | | Loki push API | `http://:3100/loki/api/v1/push` | Only when configured or managed by QoS. | +Notes: + +- If QoS metrics are enabled, it will bind a metrics listener. If you do not want a metrics endpoint, disable metrics in your QoS config. +- The query routes on the metrics endpoint are intended for convenience and debugging, not as a replacement for a full Prometheus deployment. + ## Managed Stack vs External Stack ### Managed Stack (Docker) -If the Blueprint enables `manage_servers`, QoS will launch Grafana/Loki/Prometheus containers. You should: +If the Blueprint enables `manage_servers`, QoS can launch Grafana and Loki containers (and Prometheus if configured). You should: - Ensure Docker is available on the host. - Mount persistent volumes for Grafana and Loki (`data_dir`). diff --git a/pages/vision/architecture.mdx b/pages/vision/architecture.mdx index 8083c8ae..8bd4e2ce 100644 --- a/pages/vision/architecture.mdx +++ b/pages/vision/architecture.mdx @@ -34,6 +34,9 @@ The coordination plane. It handles operator discovery, payment routing, and ince **3) Experience Layer** The agentic workbench and [Blueprint SDK](https://github.com/tangle-network/blueprint/tree/v2). This is where teams design workflows, run simulations, and ship services. +The SDK also includes optional gateways for integrating external events and payment-driven HTTP job execution (webhooks, +x402). + ## Trust and Delegation Autonomous work only scales when delegation is safe. Tangle enforces policy gates before execution, emits logs and execution metadata for every run, and keeps results reviewable so teams can decide what reaches production. diff --git a/pages/vision/core-concepts.mdx b/pages/vision/core-concepts.mdx index 4f8aa4ff..3de5221e 100644 --- a/pages/vision/core-concepts.mdx +++ b/pages/vision/core-concepts.mdx @@ -15,3 +15,5 @@ These terms show up across the docs and define how the system works. - **Economic security provider**: A participant who backs operators with assets and shares in protocol economics. - **Tangle protocol**: The coordination layer that schedules work, routes payments, and enforces incentives. - **Payments**: The flow of value tied to usage, distributed to operators and developers. +- **Webhook gateway**: An HTTP ingress path that converts external events into job executions. +- **x402 gateway**: An HTTP payment and execution path that verifies settlement via x402 and then triggers a job. diff --git a/pages/vision/introduction.mdx b/pages/vision/introduction.mdx index fea744c6..0194ae62 100644 --- a/pages/vision/introduction.mdx +++ b/pages/vision/introduction.mdx @@ -18,6 +18,7 @@ Autonomous work today is brittle: tasks run outside policy, results lack evidenc - **Managed workbench + runtime**: build, run, and review agent workflows with isolation, policy gates, and evaluation tools. - **[Blueprint SDK](https://github.com/tangle-network/blueprint/tree/v2)**: package services into reusable components with predictable interfaces. +- **Service connectivity primitives**: optional webhook ingress and paid HTTP job calls (x402) for integrating with external systems. ## Where It Goes diff --git a/pages/vision/use-cases.mdx b/pages/vision/use-cases.mdx index d8aa85d5..b9e296ac 100644 --- a/pages/vision/use-cases.mdx +++ b/pages/vision/use-cases.mdx @@ -37,3 +37,5 @@ Layers: runtime + protocol. Package an agent workflow or infrastructure service as a Blueprint, publish it once, and let others instantiate it on demand. Payments flow to operators and developers based on usage. Good for: builders who want distribution without running their own infrastructure. Layers: [Blueprint SDK](https://github.com/tangle-network/blueprint/tree/v2) + protocol. + +Some services also expose HTTP-first integration points, such as webhooks for event triggers or x402 for paid job calls. From fa310da9c7d3e0fdd900234c2859d83d53e74d8e Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Tue, 17 Feb 2026 14:38:38 -0700 Subject: [PATCH 2/4] docs: align vision pages with integration primitives - Add a high-level integration section (on-chain triggers, webhooks, x402, auth proxy) - Avoid implementation details and link to developer docs Verification: yarn lint --- pages/vision/architecture.mdx | 18 ++++++++++++++++++ pages/vision/introduction.mdx | 1 + 2 files changed, 19 insertions(+) diff --git a/pages/vision/architecture.mdx b/pages/vision/architecture.mdx index 8bd4e2ce..f3ace22f 100644 --- a/pages/vision/architecture.mdx +++ b/pages/vision/architecture.mdx @@ -37,6 +37,24 @@ The agentic workbench and [Blueprint SDK](https://github.com/tangle-network/blue The SDK also includes optional gateways for integrating external events and payment-driven HTTP job execution (webhooks, x402). +## Interfaces and Integration Points + +Not every service fits a pure on-chain request flow. Tangle supports multiple integration styles: + +- On-chain triggers: jobs and services can be created and invoked through protocol transactions. +- External triggers: operators can expose HTTP ingress (webhooks) that translate external events into job executions. +- Alternative settlement: operators can optionally accept paid HTTP job calls via x402 (stablecoin settlement on EVM + chains), then translate them into job executions. +- Multi-tenant APIs: when services expose off-chain HTTP or gRPC endpoints, operators can front them with an auth proxy + that injects tenant identity and enforces scopes. + +Developer references: + +- Job triggers map: `/developers/blueprint-runner/job-triggers` +- Webhooks: `/developers/blueprint-runner/webhooks` +- x402: `/developers/blueprint-runner/x402` +- Auth proxy: `/developers/blueprint-auth` + ## Trust and Delegation Autonomous work only scales when delegation is safe. Tangle enforces policy gates before execution, emits logs and execution metadata for every run, and keeps results reviewable so teams can decide what reaches production. diff --git a/pages/vision/introduction.mdx b/pages/vision/introduction.mdx index 0194ae62..c62722a5 100644 --- a/pages/vision/introduction.mdx +++ b/pages/vision/introduction.mdx @@ -19,6 +19,7 @@ Autonomous work today is brittle: tasks run outside policy, results lack evidenc - **Managed workbench + runtime**: build, run, and review agent workflows with isolation, policy gates, and evaluation tools. - **[Blueprint SDK](https://github.com/tangle-network/blueprint/tree/v2)**: package services into reusable components with predictable interfaces. - **Service connectivity primitives**: optional webhook ingress and paid HTTP job calls (x402) for integrating with external systems. +- **Multi-tenant service access**: when services expose off-chain HTTP or gRPC endpoints, operators can front them with an auth proxy that enforces authentication and injects tenant identity. ## Where It Goes From a9e6ca02e96e10de327a20fddd70d7626426287a Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Tue, 17 Feb 2026 14:52:41 -0700 Subject: [PATCH 3/4] fix(docs): remove v2 branch links - Update docs links from /v2 to /main for blueprint and tnt-core - Fix Tangle client context page to match current SDK names Verification: yarn lint, yarn format:check --- components/NetworkResources.tsx | 8 ++--- pages/developers/blueprint-auth.mdx | 8 ++--- .../evm-provider-context.mdx | 8 ++--- .../blueprint-contexts/introduction.mdx | 4 +-- .../blueprint-contexts/keystore-context.mdx | 8 ++--- .../tangle-client-context.mdx | 29 ++++++++++--------- pages/developers/blueprint-qos.mdx | 6 ++-- .../blueprint-runner/background-services.mdx | 6 ++-- .../developers/blueprint-runner/building.mdx | 22 +++++++------- .../developers/blueprint-runner/consumers.mdx | 6 ++-- .../blueprint-runner/introduction.mdx | 2 +- .../blueprint-runner/job-triggers.mdx | 6 ++-- pages/developers/blueprint-runner/jobs.mdx | 6 ++-- .../developers/blueprint-runner/producers.mdx | 8 ++--- pages/developers/blueprint-runner/routers.mdx | 4 +-- .../developers/blueprint-runner/webhooks.mdx | 6 ++-- pages/developers/blueprint-runner/x402.mdx | 6 ++-- pages/developers/blueprint-sdk.mdx | 22 +++++++------- pages/developers/blueprints/introduction.mdx | 8 ++--- pages/developers/blueprints/manager.mdx | 2 +- .../blueprints/pricing-and-payments.mdx | 4 +-- .../developers/blueprints/pricing-engine.mdx | 12 ++++---- pages/developers/cli/debugging.mdx | 2 +- pages/developers/cli/installation.mdx | 2 +- pages/developers/cli/keys.mdx | 2 +- pages/developers/cli/quickstart.mdx | 2 +- pages/developers/cli/tangle.mdx | 2 +- pages/developers/deployment/introduction.mdx | 2 +- .../p2p-networking/extensions/round-based.mdx | 2 +- pages/developers/p2p-networking/overview.mdx | 4 +-- pages/developers/p2p-networking/testing.mdx | 2 +- pages/developers/p2p-networking/usage.mdx | 2 +- .../system-architecture/overview.mdx | 14 ++++----- pages/developers/testing-with-tangle.mdx | 10 +++---- pages/developers/troubleshooting.mdx | 2 +- pages/infrastructure/protocol-deployment.mdx | 4 +-- pages/network/claim-airdrop.mdx | 4 +-- pages/network/network-parameters.mdx | 2 +- pages/network/overview.mdx | 2 +- pages/network/points-mechanics.mdx | 4 +-- pages/network/tokenomics/allocation.mdx | 10 +++---- pages/operators/manager/introduction.mdx | 2 +- pages/operators/manager/requirements.mdx | 2 +- pages/operators/manager/security.mdx | 2 +- pages/operators/manager/setup.mdx | 2 +- pages/operators/manager/sizing.mdx | 2 +- pages/operators/pricing/overview.mdx | 4 +-- pages/vision/architecture.mdx | 2 +- pages/vision/introduction.mdx | 4 +-- pages/vision/use-cases.mdx | 4 +-- 50 files changed, 145 insertions(+), 144 deletions(-) diff --git a/components/NetworkResources.tsx b/components/NetworkResources.tsx index e4646482..a2c34e97 100644 --- a/components/NetworkResources.tsx +++ b/components/NetworkResources.tsx @@ -56,7 +56,7 @@ const NETWORK_DATA = { property: "Protocol Contracts", value: { type: "link", - url: "https://github.com/tangle-network/tnt-core/tree/v2", + url: "https://github.com/tangle-network/tnt-core/tree/main", text: "github.com/tangle-network/tnt-core", }, }, @@ -64,7 +64,7 @@ const NETWORK_DATA = { property: "Blueprint SDK", value: { type: "link", - url: "https://github.com/tangle-network/blueprint/tree/v2", + url: "https://github.com/tangle-network/blueprint/tree/main", text: "github.com/tangle-network/blueprint", }, }, @@ -109,7 +109,7 @@ const NETWORK_DATA = { property: "Protocol Contracts", value: { type: "link", - url: "https://github.com/tangle-network/tnt-core/tree/v2", + url: "https://github.com/tangle-network/tnt-core/tree/main", text: "github.com/tangle-network/tnt-core", }, }, @@ -117,7 +117,7 @@ const NETWORK_DATA = { property: "Blueprint SDK", value: { type: "link", - url: "https://github.com/tangle-network/blueprint/tree/v2", + url: "https://github.com/tangle-network/blueprint/tree/main", text: "github.com/tangle-network/blueprint", }, }, diff --git a/pages/developers/blueprint-auth.mdx b/pages/developers/blueprint-auth.mdx index 42528b34..383c7aab 100644 --- a/pages/developers/blueprint-auth.mdx +++ b/pages/developers/blueprint-auth.mdx @@ -19,8 +19,8 @@ This page focuses on how **service users** obtain credentials and how **service Source of truth (implementation-focused): -- Auth proxy flows and endpoints: https://github.com/tangle-network/blueprint/blob/v2/crates/auth/AUTH_WORKFLOW.md -- OAuth JWT bearer assertion policy: https://github.com/tangle-network/blueprint/blob/v2/crates/auth/src/oauth/README.md +- Auth proxy flows and endpoints: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md +- OAuth JWT bearer assertion policy: https://github.com/tangle-network/blueprint/blob/main/crates/auth/src/oauth/README.md ## What It Applies To (And What It Does Not) @@ -116,7 +116,7 @@ Your upstream is responsible for: - `--auth-proxy-host` (default `0.0.0.0`) - `--auth-proxy-port` (default `8276`) -See: https://github.com/tangle-network/blueprint/blob/v2/crates/manager/src/config/mod.rs +See: https://github.com/tangle-network/blueprint/blob/main/crates/manager/src/config/mod.rs ## Configuration Status (OAuth Policy) @@ -126,4 +126,4 @@ stored by `service_id`. At time of writing, the policy format and verification rules are implemented and tested, but operator-facing tooling for managing policies may be limited. Start here: -- Policy schema + rules: https://github.com/tangle-network/blueprint/blob/v2/crates/auth/src/oauth/README.md +- Policy schema + rules: https://github.com/tangle-network/blueprint/blob/main/crates/auth/src/oauth/README.md diff --git a/pages/developers/blueprint-contexts/evm-provider-context.mdx b/pages/developers/blueprint-contexts/evm-provider-context.mdx index 37b2b1d8..01d11b05 100644 --- a/pages/developers/blueprint-contexts/evm-provider-context.mdx +++ b/pages/developers/blueprint-contexts/evm-provider-context.mdx @@ -6,7 +6,7 @@ import GithubFileReaderDisplay from '/components/GithubFileReaderDisplay'; # EVM Provider Context -SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/v2/crates/contexts +SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/main/crates/contexts The `EvmInstrumentedClientContext` trait provides a standardized [alloy-rs](https://github.com/alloy-rs) EVM provider for interacting with EVM-compatible blockchain networks in your Blueprint. @@ -15,7 +15,7 @@ The `EvmInstrumentedClientContext` trait provides a standardized [alloy-rs](http The `EvmInstrumentedClientContext` trait provides access to an EVM provider: ## Using the Context ### 1. Define Your Context -First, define your context struct that implements the `TangleEvmClientContext` trait: +First, define your context struct that implements the `TangleClientContext` trait: -### 2. Access Tangle EVM Client Functionality +### 2. Access Tangle Client Functionality -You can then use this context to access the client and interact with the Tangle EVM protocol: +You can then use this context to access the client and interact with the Tangle protocol: diff --git a/pages/developers/blueprint-qos.mdx b/pages/developers/blueprint-qos.mdx index 2e3a3718..73009f35 100644 --- a/pages/developers/blueprint-qos.mdx +++ b/pages/developers/blueprint-qos.mdx @@ -6,7 +6,7 @@ import GithubFileReaderDisplay from "/components/GithubFileReaderDisplay"; # Quality of Service (QoS) Integration Guide -SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/v2/crates/qos +SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/main/crates/qos This guide explains how to integrate the Blueprint SDK Quality of Service (QoS) system for observability, monitoring, and dashboards. QoS combines heartbeats, metrics, logs, and Grafana dashboards into a single service that you can run alongside any Blueprint. @@ -57,7 +57,7 @@ Important behavior: Reference: @@ -50,7 +50,7 @@ This creates a workspace with two main packages: Before building the runner, define the jobs that your Blueprint will execute. Jobs are defined in the library package: **Blueprints** are on-chain service definitions, and **Services** are their on-chain instantiations. Developers build -Blueprints using the [Blueprint SDK](https://github.com/tangle-network/blueprint/tree/v2) and deploy them to Tangle v2. +Blueprints using the [Blueprint SDK](https://github.com/tangle-network/blueprint/tree/main) and deploy them to Tangle v2. Customers discover Blueprints, create Services, and pay for execution. Operators run Services with the Blueprint Manager, earning fees and TNT incentives defined by the core protocol contracts in `tnt-core`. @@ -81,8 +81,8 @@ Service payments are split by the core protocol contracts in `tnt-core`: - **Staker** share flows to `ServiceFeeDistributor` for later claims. Inflation incentives (TNT) are distributed separately via `InflationPool` and `RewardVaults`. For details, see -`https://github.com/tangle-network/tnt-core/blob/v2/PAYMENT_FLOW.md` and -`https://github.com/tangle-network/tnt-core/blob/v2/docs/rewards-system.md`. +`/developers/system-architecture/rewards` and the `tnt-core` pricing integration guide: +`https://github.com/tangle-network/tnt-core/blob/main/docs/PRICING.md`. ## Composability and Ecosystem diff --git a/pages/developers/blueprints/manager.mdx b/pages/developers/blueprints/manager.mdx index f434b556..0df36319 100644 --- a/pages/developers/blueprints/manager.mdx +++ b/pages/developers/blueprints/manager.mdx @@ -2,7 +2,7 @@ import ExpandableImage from '../../../components/ExpandableImage'; ## Blueprint Manager -SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/v2/crates/manager +SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/main/crates/manager diff --git a/pages/developers/blueprints/pricing-and-payments.mdx b/pages/developers/blueprints/pricing-and-payments.mdx index c952d353..d120ebf7 100644 --- a/pages/developers/blueprints/pricing-and-payments.mdx +++ b/pages/developers/blueprints/pricing-and-payments.mdx @@ -19,7 +19,7 @@ If you are looking for the operator-side gRPC daemon that generates EIP-712 quot The most comprehensive, protocol-accurate reference lives in `tnt-core`: anyhow::Result<()> { } ``` -The harness loads the `localtestnet-state.json` snapshot shipped in the [Blueprint SDK](https://github.com/tangle-network/blueprint/tree/v2). When the snapshot is missing or +The harness loads the `localtestnet-state.json` snapshot shipped in the [Blueprint SDK](https://github.com/tangle-network/blueprint/tree/main). When the snapshot is missing or invalid, it replays the Foundry broadcast used by `tnt-core` fixtures. ### Run your blueprint against local Tangle v2 @@ -56,5 +56,5 @@ cargo tangle blueprint run \ --settings-file ./settings.env ``` -For the latest harness details and fixtures, see the [Blueprint SDK](https://github.com/tangle-network/blueprint/tree/v2) runbook: -`https://github.com/tangle-network/blueprint/blob/v2/docs/operators/anvil.md`. +For the latest harness details and fixtures, see the [Blueprint SDK](https://github.com/tangle-network/blueprint/tree/main) runbook: +`https://github.com/tangle-network/blueprint/blob/main/docs/operators/anvil.md`. diff --git a/pages/developers/troubleshooting.mdx b/pages/developers/troubleshooting.mdx index b8f13fa8..2a1c079e 100644 --- a/pages/developers/troubleshooting.mdx +++ b/pages/developers/troubleshooting.mdx @@ -30,7 +30,7 @@ Caused by: Verify that your blueprint's jobs and reports are implemented correctly. If metadata generation is failing, temporarily comment out the build script section that writes metadata and rebuild to surface compiler errors in your blueprint code. Date: Tue, 17 Feb 2026 16:07:04 -0700 Subject: [PATCH 4/4] docs(blueprints): document service renewal and expiry --- pages/developers/blueprints/_meta.ts | 1 + pages/developers/blueprints/manager.mdx | 4 + .../blueprints/pricing-and-payments.mdx | 4 + .../blueprints/service-lifecycle.mdx | 104 ++++++++++++++++++ pages/developers/cli/tangle.mdx | 4 +- 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 pages/developers/blueprints/service-lifecycle.mdx diff --git a/pages/developers/blueprints/_meta.ts b/pages/developers/blueprints/_meta.ts index 1756b56d..f19f67ca 100644 --- a/pages/developers/blueprints/_meta.ts +++ b/pages/developers/blueprints/_meta.ts @@ -3,6 +3,7 @@ import { Meta } from "nextra"; const meta: Meta = { introduction: "Introduction", "use-cases": "Use Cases", + "service-lifecycle": "Service Lifecycle", "pricing-and-payments": "Pricing & Payments", "pricing-engine": "Pricing Engine", manager: "Blueprint Manager", diff --git a/pages/developers/blueprints/manager.mdx b/pages/developers/blueprints/manager.mdx index 0df36319..a77b03be 100644 --- a/pages/developers/blueprints/manager.mdx +++ b/pages/developers/blueprints/manager.mdx @@ -26,6 +26,10 @@ Blueprints interact with the Tangle Network in several key ways: 2. Customers instantiate a Service, which represents a single configured service instance. 3. Services end once they reach their time-to-live (TTL) or run out of funds to pay operators. +For renewal, migration, and expiry edge cases, see: + +- `/developers/blueprints/service-lifecycle` + Blueprints provide a useful abstraction, allowing developers to create reusable service infrastructures as if they were smart contracts. This enables developers to monetize their work and align long-term incentives with the success of their creations, benefiting proportionally to their Blueprint's usage. Blueprints and Services are managed by the Tangle v2 contracts in `tnt-core`, including the core `Tangle` contract and diff --git a/pages/developers/blueprints/pricing-and-payments.mdx b/pages/developers/blueprints/pricing-and-payments.mdx index d120ebf7..4ad38eac 100644 --- a/pages/developers/blueprints/pricing-and-payments.mdx +++ b/pages/developers/blueprints/pricing-and-payments.mdx @@ -107,6 +107,10 @@ Service RFQ lets a user create a service instantly using operator quotes: This is separate from the request and approval service lifecycle flow that the CLI exposes under `cargo tangle blueprint service`. +For renewal and expiry semantics (including limitations of `extendServiceFromQuotes` and migration recommendations), see: + +- `/developers/blueprints/service-lifecycle` + ## Payment Tokens and Escrow (Subscription) For `Subscription`, a service owner funds escrow and billing is triggered on an interval. If escrow is insufficient, diff --git a/pages/developers/blueprints/service-lifecycle.mdx b/pages/developers/blueprints/service-lifecycle.mdx new file mode 100644 index 00000000..2d005d8b --- /dev/null +++ b/pages/developers/blueprints/service-lifecycle.mdx @@ -0,0 +1,104 @@ +--- +title: Service Lifecycle +description: Renewal, migration, and expiry semantics for services, plus safety recommendations for stateful and custodial blueprints. +--- + +# Service Lifecycle + +This page describes how service renewal, migration, and expiry work at the protocol level, and what blueprint developers +should assume when designing stateful or custodial systems. + +For the canonical on-chain API surface, see: + +- `/developers/api/reference/ITangleServices` +- `/developers/api/reference/ITangleJobs` + +## Concepts + +- **Blueprint**: the service template. +- **Service**: a single configured instance of a blueprint, created for a specific owner and operator set. +- **Service owner**: the account that owns the service and controls administrative actions such as termination. +- **Operators**: the parties that execute jobs for the service. +- **TTL**: time-to-live for a service. In the current protocol implementation, TTL checks use `block.timestamp`. A TTL of + `0` means "no expiry". + +## Creating A Service + +There are two high-level creation flows: + +1. Request and approve flow (`requestService*`): the customer requests a service and operators approve (or reject). +2. RFQ flow (`createServiceFromQuotes`): the customer collects signed operator quotes off-chain, then creates the service + on-chain in one transaction. + +The CLI primarily covers the request and approve flow. RFQ flows often require custom client code today. + +## Extending A Service (Renewal) + +The protocol supports renewal for RFQ-created services via: + +```solidity +extendServiceFromQuotes(uint64 serviceId, Types.SignedQuote[] quotes, uint64 extensionDuration) +``` + +Key properties to design around: + +- Only the **service owner** can extend a service. +- Extension applies to services that have a TTL (`ttl != 0`). +- Quotes must come from the **current operators of the service**. Extension does not change the operator set. +- Payment is provided with the transaction (for example, via `msg.value` depending on the quote format and payment asset). +- Extension can be executed even after the service has expired, as long as it is still active. The service can resume job + acceptance after TTL is increased. + +If you need to extend a service that was created via the request and approve flow, the typical path today is to create a +new service (request flow or RFQ flow), then migrate at the blueprint layer. + +## Migrating Or Rotating Operators + +If an extension requires a new operator set, the protocol does not provide a single "extend and replace operators" +transaction. + +Options depend on the blueprint membership model: + +- Fixed membership: create a new service with a new operator set, then migrate state. +- Dynamic membership: operators can join and leave an active service, subject to on-chain bounds and manager hooks. This + can be used for gradual rotation if the blueprint is built for it. + +Blueprint managers can also force-remove operators from a service for emergency response. Blueprint developers should +treat this as a last-resort tool and design for the possibility that the operator set changes unexpectedly. + +## What Expiry Means + +Expiry is enforced by function-level checks. When a service is expired (`block.timestamp > createdAt + ttl`), critical +paths like job submission and subscription billing revert. + +Expiry does not necessarily mean "terminated" in the protocol's service status. If you need explicit cleanup or refund +behavior, ensure your operational tooling calls `terminateService(serviceId)` when a service should end. + +## Safety Recommendations For Stateful Or Custodial Blueprints + +If your blueprint holds user funds, tokens, or state that must remain withdrawable, assume that: + +- Operators may not be willing to renew a service. +- A service can expire without any party submitting a renewal transaction. +- Job execution can stop permanently for that service ID. + +Recommended design patterns: + +- Provide an escape hatch that does not require fresh job execution. Examples include time-locked withdrawals, emergency + exit keys, or an explicit state migration path to a new service ID. +- Make job handlers idempotent when possible so retries and replays do not corrupt state. +- Surface TTL and renewal status to end users early. If users build a business on a service instance, renewal should be a + monitored event with alerts well before expiry. + +## Common Failure Scenarios + +### Operators Refuse To Quote A Renewal + +This is best treated as a market dynamic, not a protocol fault. A blueprint can enforce performance requirements while a +service is active, but renewal is a new agreement. If continuity is critical, design for migration to a new service with +a new operator set. + +### Service Expires With Assets Still In Use + +This is a blueprint design issue, not something the protocol can universally solve. Blueprint developers should document +what users must do before expiry, and should provide a safe way for users to exit even if the service cannot be renewed. diff --git a/pages/developers/cli/tangle.mdx b/pages/developers/cli/tangle.mdx index 3cb45d87..7030d667 100644 --- a/pages/developers/cli/tangle.mdx +++ b/pages/developers/cli/tangle.mdx @@ -90,13 +90,15 @@ Run the blueprint manager/runner against a deployment: ```bash cargo tangle blueprint run \ - --protocol tangle-evm \ + --protocol tangle \ --http-rpc-url https://... \ --ws-rpc-url wss://... \ --keystore-path ./keystore \ --settings-file ./settings.env ``` +`--protocol tangle-evm` is accepted as an alias for `--protocol tangle`. + For local validation only, you can spawn a single service without on-chain transactions: ```bash