@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 +14 -1
- package/README.md +49 -6
- package/SECURITY.md +11 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/partner.d.ts +79 -0
- package/dist/partner.d.ts.map +1 -0
- package/dist/partner.js +195 -0
- package/dist/partner.js.map +1 -0
- package/docs/PARTNER_PILOT.md +95 -0
- package/package.json +1 -1
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
|
-
|
|
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.
|
|
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;
|
|
15
|
-
>
|
|
16
|
-
> external review
|
|
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
|
-
>
|
|
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)
|
|
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.
|
|
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";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
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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"}
|
package/dist/partner.js
ADDED
|
@@ -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.
|