@ixo/decision-oracle 0.2.32 → 0.2.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -787,6 +787,6 @@ symlinks are not packed). CI diffs them — change one, copy it to the other.
|
|
|
787
787
|
|
|
788
788
|
## Status
|
|
789
789
|
|
|
790
|
-
Published on npm: `@ixo/decision-oracle` 0.2.
|
|
790
|
+
Published on npm: `@ixo/decision-oracle` 0.2.34 and `@ixo/decision-oracle-client` 0.1.3.
|
|
791
791
|
|
|
792
792
|
Apache License 2.0: `LICENSE` at the repo root and in each package.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../../src/routes/v1/info.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../../src/routes/v1/info.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAY5C,eAAO,MAAM,IAAI,qDAAqB,CAAC"}
|
package/dist/routes/v1/info.js
CHANGED
|
@@ -12,7 +12,7 @@ import { Hono } from "hono";
|
|
|
12
12
|
import { oracleWebDid } from "../../lib/ixo/ucan.js";
|
|
13
13
|
import { HIRE_PATH, SCAN_PATH } from "../../lib/openhands/routes.js";
|
|
14
14
|
import { WHY_PATH } from "../../lib/openhands/why.js";
|
|
15
|
-
import { advertisedPrice, reviewBillingActive } from "../../lib/payments/review-billing.js";
|
|
15
|
+
import { advertisedPrice, planIsIxoManaged, reviewBillingActive, } from "../../lib/payments/review-billing.js";
|
|
16
16
|
import { effectivePricing, evaluationFeeFor, getOracle } from "../../oracle.js";
|
|
17
17
|
import { nameOf } from "./api/protocols.js";
|
|
18
18
|
export const info = new Hono();
|
|
@@ -35,6 +35,7 @@ info.get("/", async (c) => {
|
|
|
35
35
|
// A marketplace listing changes by a redeploy, not by the request — long enough to spare a
|
|
36
36
|
// crawler, short enough that a price/policy edit shows up within minutes.
|
|
37
37
|
c.header("cache-control", "public, max-age=300");
|
|
38
|
+
const deps = { config, logger: c.get("logger"), trace: c.get("trace"), cache: c.env.CACHE_KV };
|
|
38
39
|
return c.json({
|
|
39
40
|
name,
|
|
40
41
|
description,
|
|
@@ -79,12 +80,11 @@ info.get("/", async (c) => {
|
|
|
79
80
|
// from the company's credits (IXO's plan for the oracle allows it; the collection's evaluation leg
|
|
80
81
|
// stays empty) — or `escrow`, the collection's on-chain evaluation payment (`pricing`).
|
|
81
82
|
// `pricePerReview` is the published per-review price, the Agent Card's.
|
|
82
|
-
reviewBilling: await reviewBillingInfo(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}),
|
|
83
|
+
reviewBilling: await reviewBillingInfo(deps),
|
|
84
|
+
// Whether IXO runs this oracle (the engine plan's `ixoManaged`, what lets register accept a
|
|
85
|
+
// `upay` fee), so an app need not keep its own list of IXO's checkers. null: the engine could
|
|
86
|
+
// not say just now.
|
|
87
|
+
ixoManaged: await planIsIxoManaged(deps).catch(() => null),
|
|
88
88
|
// An OpenHands checker (`openhands` in defineOracle) — the two webhooks the OpenHands app calls
|
|
89
89
|
// on THIS host after an ask grants this oracle, and the claimant's "why" read (lib/openhands/
|
|
90
90
|
// why.ts). Absent ⇒ not an OpenHands checker.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../../src/routes/v1/info.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../../src/routes/v1/info.ts"],"names":[],"mappings":"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"}
|
package/docs/api.md
CHANGED
|
@@ -1789,7 +1789,7 @@ check.**
|
|
|
1789
1789
|
| `GET /health/ready` | public, **rate-limited** (per IP) | `{ ok }` only — `200` when every critical check passes, `503` otherwise. Checks `d1`, `kv`, `engine` (its `/.well-known/did.json`) and, with `API_LANE` and `API_PAYMENTS` on, `facilitator` (`X402_FACILITATOR_URL/supported`), in parallel, 2 s each, plus `identity` (a config read: fails when `ORACLE_ENTITY_DID` is unset on a non-local `ORACLE_HOSTNAME`) and `owner-delegation` (fails when `OWNER_DELEGATION_CAR` is set but is not a UCAN delegation; unset passes); the settled answer is cached per isolate for 15 s. A failure before the route runs (a config that does not load) is also `503 { ok: false }`. Names no check — the detail is `/v1/admin/status`'s |
|
|
1790
1790
|
| `GET /.well-known/did.json` | public, rate-limit exempt | Needs `SERVICE_ED25519_MNEMONIC` |
|
|
1791
1791
|
| `GET /.well-known/oauth-protected-resource/v1/mcp` | public, rate-limit exempt, `Access-Control-Allow-Origin: *`, `cache-control: public, max-age=300` | RFC 9728 metadata for the MCP server: `{ resource: "https://<ORACLE_HOSTNAME>/v1/mcp", authorization_servers: [AUTH_HUB_URL], scopes_supported: ["claims:write", "claims:read"], bearer_methods_supported: ["header"] }`. `404` unless `API_LANE` is on. Outside the `/v1/api` contract |
|
|
1792
|
-
| `GET /v1/info` | **public** (the only public `/v1` path) | —. The marketplace listing: `name`, `description`, `did`, `address`, `entityDid` (the on-chain oracle entity from `ORACLE_ENTITY_DID`, `null` when unset), `serviceDid`, `lanes: { chain, api }` (booleans: `CHAIN_LANE` and `API_LANE` — a portal offers an on-chain hire only where `chain` is `true`, a console lists the oracle for the Decision API only where `api` is; the listing is cached 300 s, so a lane flip shows up to 5 min late), `supportedProtocols`, `protocols` (the same list readably: `[{ did, name, fee }]` — `name` the protocol entity's name from IXO Names (`https://names.ixo.earth`, per network — its profile name), else its claim form's title, cached 1 h, `null` when neither reads; `fee` the `{ denom, minAmount }` register charges for it), `pricing`, `policies`, `earnings: { address, baseWallet }` (the operator's `EARNINGS_ADDRESS` / `EARNINGS_BASE_WALLET`, `null` when unset — read-only, set in the oracle's config), `payouts: { decisionToPay, operatorAmount }` — how a payout amount is chosen, for a portal to show before a company opts in: `decisionToPay` is the config's `payouts` map verbatim (per protocol DID, `{ amount: <answer path>, currency: <ISO 4217 code> | { path } | { asset, decimals } }`; `{}` when none, and a protocol absent from it gets no decision to pay), `operatorAmount` is `{ summary }` from `policies.actSummary` when an `act` policy is configured, else `null` (`actSummary` is served only here, never under `policies`), and `reviewBilling: { mode, pricePerReview }` — how a collection pays for its reviews: `mode: "x402"` (per-review billing ACTIVE: IXO's plan for the oracle allows it — the engine's `GET /v1/oracles/me` `reviewBilling`, KV-cached 5 min — on an oracle running `API_LANE`: per review from the company's credits, an empty evaluation leg) with `pricePerReview: { denom: "upay", amount }` the published per-review price (the one the supported protocols share, else `pricing.api.amountMicroUsd` / `API_PRICE_USD_CENTS`; `null` when none is published), or `mode: "escrow"` (the collection's on-chain evaluation payment, `pricing`) with `pricePerReview: null
|
|
1792
|
+
| `GET /v1/info` | **public** (the only public `/v1` path) | —. The marketplace listing: `name`, `description`, `did`, `address`, `entityDid` (the on-chain oracle entity from `ORACLE_ENTITY_DID`, `null` when unset), `serviceDid`, `lanes: { chain, api }` (booleans: `CHAIN_LANE` and `API_LANE` — a portal offers an on-chain hire only where `chain` is `true`, a console lists the oracle for the Decision API only where `api` is; the listing is cached 300 s, so a lane flip shows up to 5 min late), `supportedProtocols`, `protocols` (the same list readably: `[{ did, name, fee }]` — `name` the protocol entity's name from IXO Names (`https://names.ixo.earth`, per network — its profile name), else its claim form's title, cached 1 h, `null` when neither reads; `fee` the `{ denom, minAmount }` register charges for it), `pricing`, `policies`, `earnings: { address, baseWallet }` (the operator's `EARNINGS_ADDRESS` / `EARNINGS_BASE_WALLET`, `null` when unset — read-only, set in the oracle's config), `payouts: { decisionToPay, operatorAmount }` — how a payout amount is chosen, for a portal to show before a company opts in: `decisionToPay` is the config's `payouts` map verbatim (per protocol DID, `{ amount: <answer path>, currency: <ISO 4217 code> | { path } | { asset, decimals } }`; `{}` when none, and a protocol absent from it gets no decision to pay), `operatorAmount` is `{ summary }` from `policies.actSummary` when an `act` policy is configured, else `null` (`actSummary` is served only here, never under `policies`), and `reviewBilling: { mode, pricePerReview }` — how a collection pays for its reviews: `mode: "x402"` (per-review billing ACTIVE: IXO's plan for the oracle allows it — the engine's `GET /v1/oracles/me` `reviewBilling`, KV-cached 5 min — on an oracle running `API_LANE`: per review from the company's credits, an empty evaluation leg) with `pricePerReview: { denom: "upay", amount }` the published per-review price (the one the supported protocols share, else `pricing.api.amountMicroUsd` / `API_PRICE_USD_CENTS`; `null` when none is published), or `mode: "escrow"` (the collection's on-chain evaluation payment, `pricing`) with `pricePerReview: null`, and `ixoManaged` — whether IXO runs this oracle (the engine plan's `ixoManaged`, KV-cached 5 min; what lets register accept a `upay` fee), `null` when the engine could not say. `cache-control: public, max-age=300`. With `openhands` set, also `openhands: { hire: "/openhands/hire/:collectionId", scan: "/openhands/scan/:collectionId", why: "/openhands/claims/:claimId/why" }` — absent on any other oracle. A portal is built against these exact field names |
|
|
1793
1793
|
| `POST /openhands/hire/:collectionId` | public, **`OPENHANDS_RATE_LIMITER`** (per caller and per collection; unbound outside development ⇒ `503`), `openhands` on only | With `CHAIN_LANE` `"false"`, `409 { error, reason: "chain_lane_off" }` before anything else (no limiter token, no read, no start). Starts the collection's hire (`202 { started: true }`) after reading that it exists and its admin granted this oracle a live meta-grant: `404` no such collection (not cached), `409` no meta-grant (cached 10 min). A hire in flight, or an ended one the chain says is healthy, is `200 { existing: true }` (the healthy answer cached 1 min); an ended one the chain says is stale or low is rerun from the webhook's own budget (`200 { restarted: true, reason }`, three a day, then `{ throttled: true }`). `400` a malformed id, `405` not POST, `503` when the chain or Blocksync cannot answer |
|
|
1794
1794
|
| `POST /openhands/scan/:collectionId` | public, **`OPENHANDS_RATE_LIMITER`**, `openhands` on only | Scans one watched collection now (with `CHAIN_LANE` `"false"`, `409 { error, reason: "chain_lane_off" }` first): `200 { started }`, `202 { coalesced: true }` within a minute of the last (scanned on the next minute tick), `404` not watched, `409` paused. A `200 { started: 0 }` (or a failed scan) is retried on the next three minute ticks |
|
|
1795
1795
|
| `GET /openhands/claims/:claimId/why` | **the claim's own submitter**: a UCAN invocation (`Authorization: Bearer <token>`, `X-Auth-Type: ucan`) carrying exactly `{ can: "claims/why", with: "ixo:claim:<claimId>" }`, addressed to this oracle's did:web, self-issued (no delegation), expiring at most 10 min out, whose issuer is the claim's on-chain `agentDid`. **`OPENHANDS_RATE_LIMITER`** per caller address before the token is checked and per issuer after (`429`; unbound outside development ⇒ `429`). `openhands` on only | Why the claim was decided: `200 { outcome, summary, reasons[], evidenceGrade?, reviewNote?, receiptCid? }` — `outcome` is `approved` (approve or partial) / `rejected` / `review` (held for a person) / `pending`; each reason is `{ code, label, result: pass \| fail \| error \| review, detail, value?, threshold?, unit? }`, one per gate or criterion, explained through the one fact it reads and labelled by the pinned rubric (`#rub`, read for its public sentences only, hash-checked, cached 7 days; unreadable ⇒ codes without labels). An `ext` fact's reason is never echoed (only the stock geo handlers' distances and evidence grade), an AI sentence only scrubbed of identifiers, and no AI instruction is ever read. A claim queued, or on a watched collection and not yet seen, is `pending`; a **failed ingest** is `pending` with a fixed sentence (`claimFailureReason`) — never the stored error. Anyone but the agent, or a claim this oracle never saw, gets the same `404 NOT_FOUND`; `401` no or a bad token, `400` a malformed id, `405` not GET, `503` when Blocksync or the DID resolver cannot answer |
|
package/package.json
CHANGED
|
@@ -49,7 +49,10 @@ Amounts are **integer base units** (6 decimals: `1000000` = 1 coin). The denom i
|
|
|
49
49
|
- **Third-party oracle:** IXO (`uixo`) anywhere, or on mainnet USDC — USDC.inj,
|
|
50
50
|
`ibc/77C12480BD8C29BF0ACEC2143736C15BAF8CD232CA27BAE09336677B828955E6`. **Never PAY (`upay`)**:
|
|
51
51
|
register refuses it on an oracle IXO does not run (`pay_requires_ixo_managed`).
|
|
52
|
-
- **IXO-managed oracle:** PAY (`upay`, 1 PAY = $1) is allowed
|
|
52
|
+
- **IXO-managed oracle:** PAY (`upay`, 1 PAY = $1) is allowed — but only once the decision engine
|
|
53
|
+
marks the oracle `ixoManaged` on its plan (`GET /v1/oracles/me`). IXO sets that plan, and only
|
|
54
|
+
after the oracle is registered (`engine register`). Until then every hire/register in `upay` is
|
|
55
|
+
refused `409 pay_requires_ixo_managed`. Order: register → IXO sets the plan → first hire.
|
|
53
56
|
- **Free:** `minAmount: "0"` — any evaluation leg, or none, is accepted. Bound your engine spend
|
|
54
57
|
with an `openhands.admit` hook (an allow-list, a daily budget) if anyone can hire you.
|
|
55
58
|
- Price it so your 80% share covers the engine's per-decision fee: the chain pays each evaluation
|
|
@@ -119,7 +122,7 @@ A claim marked FLAGGED while a person reviews pays nothing until its final verdi
|
|
|
119
122
|
| Worker fails to start on mainnet | `EVALUATION_DENOM` / `EVALUATION_MIN_AMOUNT` missing or only one set → set both |
|
|
120
123
|
| `/v1/info` shows the old price after deploy | mainnet: the env vars win over `src/index.ts` → edit the env's vars |
|
|
121
124
|
| Hire/register `402 evaluation_underpaid` | the collection's evaluation leg is below the minimum or in another denom → the app must escrow your coin and amount |
|
|
122
|
-
| Register refuses `pay_requires_ixo_managed` | PAY on
|
|
125
|
+
| Register refuses `pay_requires_ixo_managed` | PAY on an oracle the engine does not mark `ixoManaged` → use `uixo` or USDC.inj, or (IXO-run) have IXO set the plan after `engine register` |
|
|
123
126
|
| App shows the old price | card not refreshed (step 5) or the app hard-codes it (step 6) |
|
|
124
127
|
| `--price-pay must be a positive PAY amount` | free check: drop `--price-pay` |
|
|
125
128
|
|