@perkos/agent-sdk 0.3.2 → 0.4.0

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/CHANGELOG.md CHANGED
@@ -4,7 +4,20 @@ All notable changes to `@perkos/agent-sdk` are documented here.
4
4
 
5
5
  ## Unreleased
6
6
 
7
- No changes yet.
7
+ ### Added
8
+
9
+ - `NayoriPartnerClient` for invitation-bound wallet challenges, one-time OAuth client enrollment,
10
+ minimum-scope client-credentials tokens and authenticated MCP JSON-RPC calls.
11
+ - `createStacksConnectPartnerSigner` adapter for Leather-compatible `stx_signMessage` responses
12
+ without giving the SDK wallet key material.
13
+ - Partner-pilot documentation covering exact-message review, one-time secret handling, scopes,
14
+ MCP tools and the separate wallet payment-signing boundary.
15
+
16
+ ### Security
17
+
18
+ - Normalize and validate recoverable signatures and compressed public keys before registration.
19
+ - Keep OAuth credentials caller-owned: the SDK does not persist, log, refresh or treat them as
20
+ payment authorization.
8
21
 
9
22
  ## 0.3.2 - 2026-08-27
10
23
 
package/README.md CHANGED
@@ -9,14 +9,15 @@ This repository is the continuation of `PerkOS-xyz/PerkOS-Agent-SDK`, renamed to
9
9
  public SDK with the Nayori product identity. The npm package remains `@perkos/agent-sdk` and the
10
10
  complete Git history, releases, issues, and pull requests are preserved.
11
11
 
12
- > Status: 0.3.2 developer release. Read clients, transaction builders, browser and headless signer
12
+ > Status: 0.4.0 developer release. Read clients, transaction builders, browser and headless signer
13
13
  > adapters, confirmation receipts, safety policies, and a transactional testnet quickstart are
14
- > implemented. The x402 v2 client and Stacks facilitator foundations are implemented; hosted quote
15
- > infrastructure now exists separately, while production settlement enablement, MCP adapters,
16
- > external review, and adoption evidence remain before Milestone 2 completion. The direct x402
14
+ > implemented. The x402 v2 client and Stacks facilitator foundations are implemented; this release
15
+ > adds wallet-linked OAuth and MCP support for the planned invite-only testnet pilot. Hosted rollout,
16
+ > external review and adoption evidence remain before Milestone 2 completion. The direct x402
17
17
  > profile includes request-bound pure verification
18
18
  > and payer-side intent, policy, Leather, and remote-signer foundations for STX, sBTC, and USDCx.
19
- > It does not broadcast transactions, and hosted production settlement remains disabled.
19
+ > Every payment signature remains delegated to the configured wallet or custody boundary. Mainnet
20
+ > facilitator settlement remains disabled.
20
21
 
21
22
  ## Requirements
22
23
 
@@ -148,6 +149,43 @@ const perkos = new PerkOSClient({ network: "mainnet", signer });
148
149
  Install `@stacks/connect` in the browser application. Wallet discovery and account selection stay
149
150
  at the application boundary so the SDK cannot silently choose an account.
150
151
 
152
+ ## Invite-only partner OAuth and MCP
153
+
154
+ `NayoriPartnerClient` enrolls an invited partner without taking custody of a wallet. It requests a
155
+ single-use challenge, delegates the exact plaintext to Leather through `stx_signMessage`, submits
156
+ the signature and returns the generated OAuth client secret once. OAuth authorizes API/MCP access
157
+ only; every payment remains a separate wallet-signed transaction.
158
+
159
+ ```ts
160
+ import { request } from "@stacks/connect";
161
+ import {
162
+ NayoriPartnerClient,
163
+ createStacksConnectPartnerSigner,
164
+ } from "@perkos/agent-sdk";
165
+
166
+ const partners = new NayoriPartnerClient();
167
+ const credentials = await partners.enroll({
168
+ invitationToken,
169
+ walletAddress: connectedTestnetAddress,
170
+ signMessage: createStacksConnectPartnerSigner(request),
171
+ });
172
+
173
+ // Move the one-time secret directly into the application's secret manager.
174
+ const token = await partners.requestToken({
175
+ clientId: credentials.clientId,
176
+ clientSecret: credentials.clientSecret,
177
+ scopes: ["mcp:invoke"],
178
+ });
179
+
180
+ const tools = await partners.callMcp({
181
+ accessToken: token.accessToken,
182
+ method: "tools/list",
183
+ });
184
+ ```
185
+
186
+ See [Partner pilot](docs/PARTNER_PILOT.md) for the complete enrollment, scope and secret-handling
187
+ boundary.
188
+
151
189
  ## Headless signer
152
190
 
153
191
  `HeadlessSigner` requests key material only when deriving the public address or signing. It caches
@@ -391,11 +429,16 @@ or facilitator-submitted signed transaction.
391
429
  - Automated workflows can wait for an explicit terminal confirmation before their next action.
392
430
  - x402 quotes are bound to the configured network, escrow contract, asset, job, and exact budget.
393
431
  - x402 settlement verifies current chain evidence and atomically consumes each funding txid once.
432
+ - Partner OAuth enrollment signs an exact, short-lived, invitation-bound message in the wallet;
433
+ the SDK normalizes the public signature but never receives a private key.
434
+ - OAuth client secrets and access tokens are application secrets. The SDK returns them to the
435
+ caller but does not persist, log or refresh them automatically.
394
436
 
395
437
  This package has not yet completed the external security review required for PerkOS Milestone 2.
396
438
  Do not treat the developer release as audited software.
397
439
 
398
- See [Architecture](docs/ARCHITECTURE.md) and [Security](SECURITY.md) for the trust boundaries and
440
+ See [Architecture](docs/ARCHITECTURE.md), [Partner pilot](docs/PARTNER_PILOT.md) and
441
+ [Security](SECURITY.md) for the trust boundaries and
399
442
  responsible disclosure process.
400
443
 
401
444
  ## Development
package/SECURITY.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Release status
4
4
 
5
- `@perkos/agent-sdk` 0.2.0 is an M2 developer release and has not completed the external security
5
+ `@perkos/agent-sdk` 0.4.0 is an M2 developer release and has not completed the external security
6
6
  review required for the PerkOS Stacks Endowment milestone.
7
7
 
8
8
  Do not use this developer release to control material funds without your own review. Inspect every
@@ -40,6 +40,10 @@ disclosure.
40
40
  - Explicit direct-payment recipient, HTTPS origin, merchant, amount, fee, and session limits.
41
41
  - Concurrent payment reservations that prevent asynchronous agents from oversubscribing a budget.
42
42
  - Independent verification of every signed direct-payment transaction before facilitator submission.
43
+ - Invitation-bound partner enrollment through exact Stacks message signing, with compressed public
44
+ key and recoverable-signature validation before API submission.
45
+ - OAuth client secrets and tokens remain caller-owned and are never persisted or automatically
46
+ refreshed by the SDK.
43
47
 
44
48
  ## Key handling
45
49
 
@@ -62,6 +66,12 @@ in-process policy is defense in depth and can be bypassed by a malicious host ap
62
66
  custody service must independently authenticate callers, revalidate intent, enforce durable limits,
63
67
  and keep keys outside the agent/LLM process.
64
68
 
69
+ `createStacksConnectPartnerSigner` uses `stx_signMessage` only for the exact partner-enrollment
70
+ challenge. This signature authorizes OAuth client creation, not a payment. The host must show the
71
+ message, network and selected address to the user, move the returned one-time client secret into a
72
+ secret manager and keep invitations, signatures, secrets and access tokens out of telemetry and
73
+ prompts.
74
+
65
75
  ## Confirmation handling
66
76
 
67
77
  A broadcast receipt means a node accepted the transaction, not that the contract call succeeded.
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export { SpendingPolicy } from "./policy.js";
4
4
  export { HeadlessSigner, StacksConnectSigner } from "./signers.js";
5
5
  export { TransactionTracker } from "./tracker.js";
6
6
  export { PerkOSError } from "./errors.js";
7
+ export { NAYORI_PARTNER_SCOPES, NayoriPartnerApiError, NayoriPartnerClient, createStacksConnectPartnerSigner, } from "./partner.js";
7
8
  export { DEFAULT_DEPLOYMENTS, JOB_STATUS, CLARITY_ERROR_MESSAGES } from "./constants.js";
8
9
  export { resolveConfig, toUint } from "./validation.js";
9
10
  export { normalizeTxid } from "./txid.js";
@@ -15,6 +16,7 @@ export type { HeadlessSignerOptions, HeadlessTransactionExecutor, HeadlessTransa
15
16
  export type { TrackerFetch, TransactionTrackerOptions, } from "./tracker.js";
16
17
  export type { AgentEndpoint, AgentRecord, Amount, AmountLike, AssignProviderInput, ConfirmationOptions, ConfirmedTransactionReceipt, ContractCallPlan, ContractId, CreateJobInput, FundJobInput, JobAmountInput, JobRecord, JobStatus, PaymentAsset, PerkOSConfig, PerkOSContracts, PerkOSNetwork, PerkOSOperation, PerkOSSigner, RateProviderInput, ReadOnlyCall, ReadOnlyTransport, RegisterAgentInput, ReputationRecord, ResolvedPerkOSConfig, SettleJobInput, SignerResult, SpendingApproval, SpendingPolicyInput, SubmitWorkInput, TransactionIntent, TransactionConfirmation, TransactionConfirmationStatus, TransactionReceipt, TransactionResultValue, TransactionTrackerLike, UpdateAgentInput, } from "./types.js";
17
18
  export type { PerkOSErrorCode, PerkOSErrorDetails } from "./errors.js";
19
+ export type { NayoriPartnerAccessToken, NayoriPartnerChallenge, NayoriPartnerCredentials, NayoriPartnerFetch, NayoriPartnerMessageSignature, NayoriPartnerMessageSigner, NayoriPartnerNetwork, NayoriPartnerScope, StacksConnectMessageRequest, } from "./partner.js";
18
20
  export type { ParsedPerkOSX402Requirement, PaymentPayload, PaymentRequired, PaymentRequirements, PerkOSX402ClientLike, PerkOSX402PaymentProof, PerkOSX402PaymentRequiredInput, PerkOSX402SchemeClientOptions, ResourceInfo, SettleResponse, } from "./x402.js";
19
21
  export type { HiroX402TransactionSourceOptions, PerkOSX402FacilitatorOptions, PerkOSX402ReplayRecord, PerkOSX402ReplayStore, PerkOSX402TransactionSource, PerkOSX402VerifiedPayment, X402VerifierFetch, } from "./x402-facilitator.js";
20
22
  export type { NayoriStacksX402Network, NayoriX402AssetDefinition, NayoriX402DirectPaymentPayloadInput, NayoriX402PaymentAsset, NayoriX402ProtectedRequest, NayoriX402Quote, NayoriX402QuoteInput, NayoriX402VerifiedDirectPayment, NayoriX402ValidatedPaymentContext, ValidateNayoriX402PaymentContextInput, VerifyNayoriX402DirectPaymentInput, } from "./x402-direct.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,iCAAiC,EACjC,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,YAAY,EACZ,+BAA+B,EAC/B,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,qBAAqB,EACrB,6BAA6B,EAC7B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,yBAAyB,EACzB,wCAAwC,EACxC,+BAA+B,EAC/B,oCAAoC,EACpC,yBAAyB,EACzB,iCAAiC,EACjC,2BAA2B,EAC3B,iCAAiC,EACjC,oCAAoC,EACpC,mCAAmC,EACnC,qBAAqB,EACrB,gCAAgC,EAChC,kBAAkB,EAClB,yBAAyB,EACzB,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,iCAAiC,EACjC,kCAAkC,EAClC,uBAAuB,EACvB,uBAAuB,EACvB,YAAY,EACZ,yCAAyC,EACzC,6BAA6B,GAC9B,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,kBAAkB,EAClB,kBAAkB,EAClB,+BAA+B,EAC/B,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,YAAY,EACZ,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,aAAa,EACb,WAAW,EACX,MAAM,EACN,UAAU,EACV,mBAAmB,EACnB,mBAAmB,EACnB,2BAA2B,EAC3B,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,SAAS,EACT,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,aAAa,EACb,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,6BAA6B,EAC7B,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EACV,2BAA2B,EAC3B,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,8BAA8B,EAC9B,6BAA6B,EAC7B,YAAY,EACZ,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,gCAAgC,EAChC,4BAA4B,EAC5B,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,uBAAuB,EACvB,yBAAyB,EACzB,mCAAmC,EACnC,sBAAsB,EACtB,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,+BAA+B,EAC/B,iCAAiC,EACjC,qCAAqC,EACrC,kCAAkC,GACnC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,cAAc,EACd,4BAA4B,EAC5B,oBAAoB,EACpB,8BAA8B,EAC9B,8BAA8B,EAC9B,uBAAuB,EACvB,4BAA4B,EAC5B,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC5B,uBAAuB,EACvB,6BAA6B,EAC7B,yBAAyB,EACzB,2BAA2B,EAC3B,2BAA2B,EAC3B,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ export { SpendingPolicy } from "./policy.js";
4
4
  export { HeadlessSigner, StacksConnectSigner } from "./signers.js";
5
5
  export { TransactionTracker } from "./tracker.js";
6
6
  export { PerkOSError } from "./errors.js";
7
+ export { NAYORI_PARTNER_SCOPES, NayoriPartnerApiError, NayoriPartnerClient, createStacksConnectPartnerSigner, } from "./partner.js";
7
8
  export { DEFAULT_DEPLOYMENTS, JOB_STATUS, CLARITY_ERROR_MESSAGES } from "./constants.js";
8
9
  export { resolveConfig, toUint } from "./validation.js";
9
10
  export { normalizeTxid } from "./txid.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,iCAAiC,EACjC,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,YAAY,EACZ,+BAA+B,EAC/B,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,qBAAqB,EACrB,6BAA6B,EAC7B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,yBAAyB,EACzB,wCAAwC,EACxC,+BAA+B,EAC/B,oCAAoC,EACpC,yBAAyB,EACzB,iCAAiC,EACjC,2BAA2B,EAC3B,iCAAiC,EACjC,oCAAoC,EACpC,mCAAmC,EACnC,qBAAqB,EACrB,gCAAgC,EAChC,kBAAkB,EAClB,yBAAyB,EACzB,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,iCAAiC,EACjC,kCAAkC,EAClC,uBAAuB,EACvB,uBAAuB,EACvB,YAAY,EACZ,yCAAyC,EACzC,6BAA6B,GAC9B,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,gCAAgC,GACjC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,iCAAiC,EACjC,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,YAAY,EACZ,+BAA+B,EAC/B,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,qBAAqB,EACrB,6BAA6B,EAC7B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,yBAAyB,EACzB,wCAAwC,EACxC,+BAA+B,EAC/B,oCAAoC,EACpC,yBAAyB,EACzB,iCAAiC,EACjC,2BAA2B,EAC3B,iCAAiC,EACjC,oCAAoC,EACpC,mCAAmC,EACnC,qBAAqB,EACrB,gCAAgC,EAChC,kBAAkB,EAClB,yBAAyB,EACzB,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,iCAAiC,EACjC,kCAAkC,EAClC,uBAAuB,EACvB,uBAAuB,EACvB,YAAY,EACZ,yCAAyC,EACzC,6BAA6B,GAC9B,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,79 @@
1
+ export declare const NAYORI_PARTNER_SCOPES: readonly ["catalog:read", "quotes:create", "payments:verify", "payments:settle", "payments:read", "mcp:invoke"];
2
+ export type NayoriPartnerScope = (typeof NAYORI_PARTNER_SCOPES)[number];
3
+ export type NayoriPartnerNetwork = "testnet" | "mainnet";
4
+ export type NayoriPartnerFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
5
+ export type NayoriPartnerChallenge = {
6
+ readonly challengeId: string;
7
+ readonly message: string;
8
+ readonly expiresAt: string;
9
+ readonly walletAddress: string;
10
+ readonly network: NayoriPartnerNetwork;
11
+ };
12
+ export type NayoriPartnerCredentials = {
13
+ readonly clientId: string;
14
+ readonly clientSecret: string;
15
+ readonly tokenEndpoint: string;
16
+ readonly scopes: readonly NayoriPartnerScope[];
17
+ readonly walletAddress: string;
18
+ };
19
+ export type NayoriPartnerAccessToken = {
20
+ readonly accessToken: string;
21
+ readonly tokenType: "Bearer";
22
+ readonly expiresIn: number;
23
+ readonly scopes: readonly NayoriPartnerScope[];
24
+ };
25
+ export type NayoriPartnerMessageSignature = {
26
+ readonly signature: string;
27
+ readonly publicKey: string;
28
+ };
29
+ export type NayoriPartnerMessageSigner = (input: {
30
+ readonly message: string;
31
+ readonly walletAddress: string;
32
+ readonly network: NayoriPartnerNetwork;
33
+ }) => Promise<NayoriPartnerMessageSignature>;
34
+ export type StacksConnectMessageRequest = (method: "stx_signMessage", params: {
35
+ readonly message: string;
36
+ }) => Promise<{
37
+ readonly signature: string;
38
+ readonly publicKey: string;
39
+ }>;
40
+ export declare class NayoriPartnerApiError extends Error {
41
+ readonly status: number;
42
+ readonly code: string;
43
+ constructor(status: number, code: string, message: string);
44
+ }
45
+ export declare function createStacksConnectPartnerSigner(request: StacksConnectMessageRequest): NayoriPartnerMessageSigner;
46
+ export declare class NayoriPartnerClient {
47
+ readonly origin: string;
48
+ private readonly fetchImpl;
49
+ constructor(options?: {
50
+ readonly origin?: string;
51
+ readonly fetch?: NayoriPartnerFetch;
52
+ });
53
+ requestChallenge(input: {
54
+ readonly invitationToken: string;
55
+ readonly walletAddress: string;
56
+ }): Promise<NayoriPartnerChallenge>;
57
+ register(input: {
58
+ readonly challengeId: string;
59
+ readonly signature: string;
60
+ readonly publicKey: string;
61
+ }): Promise<NayoriPartnerCredentials>;
62
+ enroll(input: {
63
+ readonly invitationToken: string;
64
+ readonly walletAddress: string;
65
+ readonly signMessage: NayoriPartnerMessageSigner;
66
+ }): Promise<NayoriPartnerCredentials>;
67
+ requestToken(input: {
68
+ readonly clientId: string;
69
+ readonly clientSecret: string;
70
+ readonly scopes?: readonly NayoriPartnerScope[];
71
+ }): Promise<NayoriPartnerAccessToken>;
72
+ callMcp(input: {
73
+ readonly accessToken: string;
74
+ readonly id?: string | number;
75
+ readonly method: "initialize" | "ping" | "tools/list" | "tools/call";
76
+ readonly params?: unknown;
77
+ }): Promise<Record<string, unknown>>;
78
+ }
79
+ //# sourceMappingURL=partner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partner.d.ts","sourceRoot":"","sources":["../src/partner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,195 @@
1
+ export const NAYORI_PARTNER_SCOPES = [
2
+ "catalog:read",
3
+ "quotes:create",
4
+ "payments:verify",
5
+ "payments:settle",
6
+ "payments:read",
7
+ "mcp:invoke",
8
+ ];
9
+ export class NayoriPartnerApiError extends Error {
10
+ status;
11
+ code;
12
+ constructor(status, code, message) {
13
+ super(message);
14
+ this.status = status;
15
+ this.code = code;
16
+ this.name = "NayoriPartnerApiError";
17
+ }
18
+ }
19
+ function apiOrigin(value) {
20
+ const url = new URL(value ?? "https://api.nayori.ai");
21
+ const local = url.hostname === "localhost" || url.hostname === "127.0.0.1";
22
+ if (url.protocol !== "https:" && !local) {
23
+ throw new Error("Nayori partner API origin must use HTTPS outside local development.");
24
+ }
25
+ return url.origin;
26
+ }
27
+ function object(value, label) {
28
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29
+ throw new Error(`${label} is invalid.`);
30
+ }
31
+ return value;
32
+ }
33
+ function string(value, label) {
34
+ if (typeof value !== "string" || value.length === 0)
35
+ throw new Error(`${label} is invalid.`);
36
+ return value;
37
+ }
38
+ function normalizedHex(value, pattern, label) {
39
+ const normalized = value.startsWith("0x") ? value.slice(2) : value;
40
+ if (!pattern.test(normalized))
41
+ throw new Error(`${label} is invalid.`);
42
+ return normalized;
43
+ }
44
+ function scopes(value) {
45
+ if (!Array.isArray(value) ||
46
+ value.length === 0 ||
47
+ value.some((scope) => typeof scope !== "string" ||
48
+ !NAYORI_PARTNER_SCOPES.includes(scope))) {
49
+ throw new Error("Nayori partner scopes are invalid.");
50
+ }
51
+ return value;
52
+ }
53
+ async function responseJson(response) {
54
+ let payload = {};
55
+ try {
56
+ payload = object(await response.json(), "Nayori API response");
57
+ }
58
+ catch {
59
+ if (response.ok)
60
+ throw new Error("Nayori API returned invalid JSON.");
61
+ }
62
+ if (!response.ok) {
63
+ const nested = payload.error && typeof payload.error === "object"
64
+ ? payload.error
65
+ : null;
66
+ const code = (typeof payload.error === "string" && payload.error) ||
67
+ (nested && typeof nested.code === "string" && nested.code) ||
68
+ "nayori_api_error";
69
+ const message = (typeof payload.error_description === "string" && payload.error_description) ||
70
+ (nested && typeof nested.message === "string" && nested.message) ||
71
+ `Nayori API returned HTTP ${response.status}.`;
72
+ throw new NayoriPartnerApiError(response.status, code, message);
73
+ }
74
+ return payload;
75
+ }
76
+ export function createStacksConnectPartnerSigner(request) {
77
+ return async ({ message }) => {
78
+ const result = await request("stx_signMessage", { message });
79
+ return {
80
+ signature: normalizedHex(result.signature, /^[0-9a-f]{130}$/i, "Leather signature"),
81
+ publicKey: normalizedHex(result.publicKey, /^(02|03)[0-9a-f]{64}$/i, "Leather public key"),
82
+ };
83
+ };
84
+ }
85
+ export class NayoriPartnerClient {
86
+ origin;
87
+ fetchImpl;
88
+ constructor(options = {}) {
89
+ this.origin = apiOrigin(options.origin);
90
+ this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);
91
+ }
92
+ async requestChallenge(input) {
93
+ const response = await this.fetchImpl(`${this.origin}/v1/partners/challenges`, {
94
+ method: "POST",
95
+ headers: { Accept: "application/json", "Content-Type": "application/json" },
96
+ body: JSON.stringify(input),
97
+ });
98
+ const payload = await responseJson(response);
99
+ const challenge = object(payload.challenge, "Nayori partner challenge");
100
+ const network = string(challenge.network, "challenge.network");
101
+ if (network !== "testnet" && network !== "mainnet") {
102
+ throw new Error("challenge.network is invalid.");
103
+ }
104
+ return {
105
+ challengeId: string(challenge.challengeId, "challenge.challengeId"),
106
+ message: string(challenge.message, "challenge.message"),
107
+ expiresAt: string(challenge.expiresAt, "challenge.expiresAt"),
108
+ walletAddress: string(challenge.walletAddress, "challenge.walletAddress"),
109
+ network,
110
+ };
111
+ }
112
+ async register(input) {
113
+ const response = await this.fetchImpl(`${this.origin}/v1/partners/register`, {
114
+ method: "POST",
115
+ headers: { Accept: "application/json", "Content-Type": "application/json" },
116
+ body: JSON.stringify({
117
+ challengeId: input.challengeId,
118
+ signature: normalizedHex(input.signature, /^[0-9a-f]{130}$/i, "wallet signature"),
119
+ publicKey: normalizedHex(input.publicKey, /^(02|03)[0-9a-f]{64}$/i, "wallet public key"),
120
+ }),
121
+ });
122
+ const payload = await responseJson(response);
123
+ const client = object(payload.client, "Nayori OAuth client");
124
+ return {
125
+ clientId: string(client.clientId, "client.clientId"),
126
+ clientSecret: string(client.clientSecret, "client.clientSecret"),
127
+ tokenEndpoint: string(client.tokenEndpoint, "client.tokenEndpoint"),
128
+ scopes: scopes(client.scopes),
129
+ walletAddress: string(client.walletAddress, "client.walletAddress"),
130
+ };
131
+ }
132
+ async enroll(input) {
133
+ const challenge = await this.requestChallenge(input);
134
+ if (challenge.walletAddress !== input.walletAddress) {
135
+ throw new Error("Nayori challenge wallet does not match the requested wallet.");
136
+ }
137
+ const signed = await input.signMessage({
138
+ message: challenge.message,
139
+ walletAddress: challenge.walletAddress,
140
+ network: challenge.network,
141
+ });
142
+ const credentials = await this.register({
143
+ challengeId: challenge.challengeId,
144
+ ...signed,
145
+ });
146
+ if (credentials.walletAddress !== input.walletAddress) {
147
+ throw new Error("Nayori OAuth client wallet does not match the enrolled wallet.");
148
+ }
149
+ return credentials;
150
+ }
151
+ async requestToken(input) {
152
+ const body = new URLSearchParams({ grant_type: "client_credentials" });
153
+ if (input.scopes?.length)
154
+ body.set("scope", scopes([...input.scopes]).join(" "));
155
+ const response = await this.fetchImpl(`${this.origin}/oauth/token`, {
156
+ method: "POST",
157
+ headers: {
158
+ Accept: "application/json",
159
+ Authorization: `Basic ${btoa(`${input.clientId}:${input.clientSecret}`)}`,
160
+ "Content-Type": "application/x-www-form-urlencoded",
161
+ },
162
+ body: body.toString(),
163
+ });
164
+ const payload = await responseJson(response);
165
+ if (payload.token_type !== "Bearer")
166
+ throw new Error("Nayori token type is invalid.");
167
+ if (typeof payload.expires_in !== "number" || !Number.isSafeInteger(payload.expires_in)) {
168
+ throw new Error("Nayori token expiry is invalid.");
169
+ }
170
+ return {
171
+ accessToken: string(payload.access_token, "access_token"),
172
+ tokenType: "Bearer",
173
+ expiresIn: payload.expires_in,
174
+ scopes: scopes(string(payload.scope, "scope").split(" ")),
175
+ };
176
+ }
177
+ async callMcp(input) {
178
+ const response = await this.fetchImpl(`${this.origin}/mcp`, {
179
+ method: "POST",
180
+ headers: {
181
+ Accept: "application/json",
182
+ Authorization: `Bearer ${input.accessToken}`,
183
+ "Content-Type": "application/json",
184
+ },
185
+ body: JSON.stringify({
186
+ jsonrpc: "2.0",
187
+ id: input.id ?? 1,
188
+ method: input.method,
189
+ ...(input.params === undefined ? {} : { params: input.params }),
190
+ }),
191
+ });
192
+ return responseJson(response);
193
+ }
194
+ }
195
+ //# sourceMappingURL=partner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partner.js","sourceRoot":"","sources":["../src/partner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ # Nayori invite-only partner pilot
2
+
3
+ The partner pilot exposes the Nayori x402 Platform on Stacks testnet without giving the API or SDK
4
+ custody of a wallet. An operator privately creates a single-use invitation for an existing merchant.
5
+ The partner binds that invitation to a Stacks address by signing the exact server challenge in
6
+ Leather. The server derives the address from the returned public key and atomically consumes both
7
+ the invitation and challenge before creating the OAuth client.
8
+
9
+ ## Browser enrollment
10
+
11
+ Install the SDK and the official Stacks Connect package:
12
+
13
+ ```bash
14
+ npm install @perkos/agent-sdk @stacks/connect
15
+ ```
16
+
17
+ Use the account already selected by the application. The SDK never selects an account and never
18
+ receives a private key:
19
+
20
+ ```ts
21
+ import { request } from "@stacks/connect";
22
+ import {
23
+ NayoriPartnerClient,
24
+ createStacksConnectPartnerSigner,
25
+ } from "@perkos/agent-sdk";
26
+
27
+ const nayori = new NayoriPartnerClient({ origin: "https://api.nayori.ai" });
28
+ const credentials = await nayori.enroll({
29
+ invitationToken,
30
+ walletAddress: selectedTestnetAddress,
31
+ signMessage: createStacksConnectPartnerSigner(request),
32
+ });
33
+ ```
34
+
35
+ Leather displays the exact challenge. Verify the origin, `testnet` network, merchant, wallet,
36
+ challenge identifier and expiration before approving. The client rejects a response bound to a
37
+ different wallet. The API independently verifies the recoverable signature and derived address.
38
+
39
+ `clientSecret` is returned once. Send it directly to an application-owned secret manager. Do not
40
+ put the invitation, client secret, access token or wallet signature in source, screenshots, logs,
41
+ analytics, issue trackers or prompts.
42
+
43
+ ## Scoped access token
44
+
45
+ Request only the scopes needed by the current process:
46
+
47
+ ```ts
48
+ const token = await nayori.requestToken({
49
+ clientId: credentials.clientId,
50
+ clientSecret: credentials.clientSecret,
51
+ scopes: ["quotes:create", "mcp:invoke"],
52
+ });
53
+ ```
54
+
55
+ Supported scopes are:
56
+
57
+ - `catalog:read`
58
+ - `quotes:create`
59
+ - `payments:verify`
60
+ - `payments:settle`
61
+ - `payments:read`
62
+ - `mcp:invoke`
63
+
64
+ The API uses `client_credentials` plus `client_secret_basic` and returns a short-lived EdDSA JWT.
65
+ The SDK deliberately does not persist or automatically refresh it.
66
+
67
+ ## MCP
68
+
69
+ The authenticated Streamable HTTP endpoint implements JSON-RPC `initialize`, `ping`, `tools/list`
70
+ and `tools/call`. Current tools are `nayori_supported`, `nayori_request_quote` and
71
+ `nayori_get_settlement`.
72
+
73
+ ```ts
74
+ const response = await nayori.callMcp({
75
+ accessToken: token.accessToken,
76
+ method: "tools/call",
77
+ params: {
78
+ name: "nayori_supported",
79
+ arguments: {},
80
+ },
81
+ });
82
+ ```
83
+
84
+ `mcp:invoke` opens the MCP endpoint, while a quote or settlement tool also enforces its own
85
+ downstream scope and merchant isolation.
86
+
87
+ ## Payment boundary
88
+
89
+ OAuth and the enrollment signature cannot authorize a payment. For each STX, sBTC or USDCx
90
+ payment, create a request-bound quote and let the payer separately inspect and sign the exact Stacks
91
+ transaction. Quote issuance, verification, broadcast or `pending` state is not confirmed
92
+ settlement. Require the confirmed settlement state and signed receipt before delivery.
93
+
94
+ The hosted pilot remains Stacks-testnet-only. Mainnet facilitator settlement, sponsorship and
95
+ arbitrary resource proxying remain disabled while the external review gate is open.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perkos/agent-sdk",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "TypeScript SDK for agent identity, escrow settlement, and reputation on Stacks.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",