@clawcash/forge 0.1.5 → 0.1.8

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/dist/index.d.cts CHANGED
@@ -72,14 +72,19 @@ interface MountOptions {
72
72
  /** Skip x402 (local dev only). Defaults to false. */
73
73
  skipPayment?: boolean;
74
74
  /**
75
- * Optional gateway heartbeat after mount.
76
- * Prefer env: GATEWAY_URL, FORGE_HANDLE, GATEWAY_REGISTER_SECRET, PUBLIC_BASE_URL.
75
+ * Gateway heartbeat after mount. Only FORGE_API_KEY is required as env;
76
+ * the URL defaults to the ClawCash gateway, the handle is baked by Forge
77
+ * codegen, and the public base URL is resolved from platform vars or
78
+ * inferred (self-verified) from the first inbound probe.
77
79
  */
78
80
  gateway?: {
81
+ /** Defaults to https://gateway.clawca.sh (or GATEWAY_URL env). */
79
82
  url?: string;
83
+ /** Merchant handle — baked by Forge codegen (or FORGE_HANDLE env). */
80
84
  handle?: string;
85
+ /** @deprecated Prefer FORGE_API_KEY env — per-project key from Forge dashboard. */
81
86
  registerSecret?: string;
82
- /** Merchant public base URL for fulfillment. */
87
+ /** Merchant public base URL. Usually omitted — resolved automatically. */
83
88
  publicBaseUrl?: string;
84
89
  };
85
90
  /**
@@ -103,6 +108,7 @@ declare function defineAgentService<TInput extends Record<string, unknown> = Rec
103
108
 
104
109
  /**
105
110
  * Mount Forge agent services on an Express app.
111
+ * - GET /forge/health, GET /forge/status, GET /.well-known/clawcash.json — liveliness
106
112
  * - POST {basePath}/{kebab-name} — optional public x402 agent surface
107
113
  * - POST /forge/fulfill/{kebab-name} — private gateway fulfillment after payment
108
114
  *
@@ -133,6 +139,42 @@ declare function resolvePayTo(opts: {
133
139
  timeoutMs?: number;
134
140
  }): Promise<string>;
135
141
 
142
+ /**
143
+ * Public base URL resolution, in trust order:
144
+ * 1. PUBLIC_BASE_URL env — explicit override.
145
+ * 2. Platform-provided vars (Railway, Render, Vercel, Fly, Heroku) — set by
146
+ * the host, not by request input, so safe to trust as-is.
147
+ * 3. Lazy inference from the first inbound request to the Forge surface
148
+ * (X-Forwarded-Proto + Host). Host is attacker-controlled, so a candidate
149
+ * is only accepted after self-verification: we fetch our own
150
+ * /forge/health at the candidate URL and check it returns this
151
+ * instance's boot nonce.
152
+ */
153
+ declare function resolveBaseUrlFromEnv(explicit?: string): string | null;
154
+ declare class PublicBaseUrlResolver {
155
+ /** Per-boot nonce, echoed by /forge/health for self-verification. */
156
+ readonly instanceNonce: string;
157
+ private resolved;
158
+ private verifying;
159
+ private rejected;
160
+ private attempts;
161
+ private onResolved;
162
+ constructor(opts: {
163
+ /** URL already known from env/platform vars (trusted, no verification). */
164
+ initial: string | null;
165
+ /** Called once when a base URL first becomes known via inference. */
166
+ onResolved?: (baseUrl: string) => void;
167
+ });
168
+ get(): string | null;
169
+ /**
170
+ * Feed an inbound Forge-surface request. No-op once resolved. Kicks off
171
+ * async self-verification of the candidate URL derived from the request.
172
+ */
173
+ considerRequest(req: Request): void;
174
+ /** Fetch our own /forge/health at the candidate and match the boot nonce. */
175
+ private verify;
176
+ }
177
+
136
178
  /**
137
179
  * Notify ClawCash gateway of this merchant's live public base URL.
138
180
  * Full action registration still happens from Forge "Go live".
@@ -145,9 +187,82 @@ declare function heartbeatGateway(opts: {
145
187
  }): Promise<void>;
146
188
 
147
189
  /**
148
- * Shared secret auth for ClawCash gateway merchant fulfillment.
149
- * Same secret as GATEWAY_REGISTER_SECRET (Forge go-live / heartbeat).
190
+ * Merchant-side Forge surface status — public probes for deploy / go-live checks.
191
+ */
192
+ type ForgeHeartbeatState = {
193
+ attempted: boolean;
194
+ ok: boolean | null;
195
+ at: string | null;
196
+ error: string | null;
197
+ };
198
+ type ForgeSurfaceStatus = {
199
+ ok: boolean;
200
+ forge: true;
201
+ version: string;
202
+ handle: string | null;
203
+ publicBaseUrl: string | null;
204
+ gatewayUrl: string | null;
205
+ /** True when FORGE_API_KEY is set so /forge/fulfill is mounted. */
206
+ fulfillMounted: boolean;
207
+ fulfillPath: string;
208
+ agentBasePath: string;
209
+ skipPayment: boolean;
210
+ actions: Array<{
211
+ name: string;
212
+ path: string;
213
+ price: string;
214
+ }>;
215
+ /** Env + fulfill ready — merchant can accept gateway fulfillment. */
216
+ ready: boolean;
217
+ heartbeat: ForgeHeartbeatState;
218
+ endpoints: {
219
+ health: string;
220
+ status: string;
221
+ wellKnown: string;
222
+ fulfill: string;
223
+ agent: string;
224
+ };
225
+ };
226
+ declare function recordHeartbeatResult(result: {
227
+ ok: true;
228
+ } | {
229
+ ok: false;
230
+ error: string;
231
+ }): void;
232
+ declare function getLastHeartbeat(): ForgeHeartbeatState;
233
+ declare function buildForgeSurfaceStatus(opts: {
234
+ handle: string | null;
235
+ publicBaseUrl: string | null;
236
+ gatewayUrl: string | null;
237
+ fulfillMounted: boolean;
238
+ fulfillPath: string;
239
+ agentBasePath: string;
240
+ skipPayment: boolean;
241
+ actions: Array<{
242
+ name: string;
243
+ path: string;
244
+ price: string;
245
+ }>;
246
+ }): ForgeSurfaceStatus;
247
+ declare function buildWellKnownDocument(status: ForgeSurfaceStatus): {
248
+ forge: true;
249
+ version: string;
250
+ health: string;
251
+ status: string;
252
+ handle: string | null;
253
+ ready: boolean;
254
+ };
255
+ declare function forgeSdkVersion(): string;
256
+
257
+ /**
258
+ * Per-project Forge API key for gateway → merchant fulfillment.
259
+ * Merchants set FORGE_API_KEY from the Forge dashboard (never the shared
260
+ * GATEWAY_REGISTER_SECRET — that is Forge↔gateway platform auth only).
261
+ *
262
+ * GATEWAY_REGISTER_SECRET is accepted as a deprecated fallback for older deploys.
150
263
  */
264
+ declare function getForgeApiKey(explicit?: string | null): string | null;
265
+ /** @deprecated Use getForgeApiKey */
151
266
  declare function getForgeGatewaySecret(explicit?: string | null): string | null;
152
267
  declare function isForgeGatewayRequest(req: Request, secret?: string | null): boolean;
153
268
  /** Synthetic user id for DB rows created by gateway-driven fulfillment. */
@@ -156,4 +271,4 @@ declare function requireForgeGateway(secret?: string | null): (req: Request, res
156
271
  /** Headers merchant execute() should send on loopback calls during fulfillment. */
157
272
  declare function forgeGatewayLoopbackHeaders(secret?: string | null): Record<string, string>;
158
273
 
159
- export { type AgentServiceConfig, type AgentServiceContext, type DefinedAgentService, FORGE_GATEWAY_USER_ID, type ForgePayToSource, type InputSchema, type MountOptions, type OutputSchema, type PaymentConfig, type SchemaFieldType, type SkillMeta, type WaitUntilOptions, createContext, createForgeRouter, defineAgentService, forgeGatewayLoopbackHeaders, generateSkillMarkdown, getForgeGatewaySecret, heartbeatGateway, isForgeGatewayRequest, isZeroAddress, mountAgentServices, requireForgeGateway, resolvePayTo, toKebabCase, waitUntil };
274
+ export { type AgentServiceConfig, type AgentServiceContext, type DefinedAgentService, FORGE_GATEWAY_USER_ID, type ForgeHeartbeatState, type ForgePayToSource, type ForgeSurfaceStatus, type InputSchema, type MountOptions, type OutputSchema, type PaymentConfig, PublicBaseUrlResolver, type SchemaFieldType, type SkillMeta, type WaitUntilOptions, buildForgeSurfaceStatus, buildWellKnownDocument, createContext, createForgeRouter, defineAgentService, forgeGatewayLoopbackHeaders, forgeSdkVersion, generateSkillMarkdown, getForgeApiKey, getForgeGatewaySecret, getLastHeartbeat, heartbeatGateway, isForgeGatewayRequest, isZeroAddress, mountAgentServices, recordHeartbeatResult, requireForgeGateway, resolveBaseUrlFromEnv, resolvePayTo, toKebabCase, waitUntil };
package/dist/index.d.ts CHANGED
@@ -72,14 +72,19 @@ interface MountOptions {
72
72
  /** Skip x402 (local dev only). Defaults to false. */
73
73
  skipPayment?: boolean;
74
74
  /**
75
- * Optional gateway heartbeat after mount.
76
- * Prefer env: GATEWAY_URL, FORGE_HANDLE, GATEWAY_REGISTER_SECRET, PUBLIC_BASE_URL.
75
+ * Gateway heartbeat after mount. Only FORGE_API_KEY is required as env;
76
+ * the URL defaults to the ClawCash gateway, the handle is baked by Forge
77
+ * codegen, and the public base URL is resolved from platform vars or
78
+ * inferred (self-verified) from the first inbound probe.
77
79
  */
78
80
  gateway?: {
81
+ /** Defaults to https://gateway.clawca.sh (or GATEWAY_URL env). */
79
82
  url?: string;
83
+ /** Merchant handle — baked by Forge codegen (or FORGE_HANDLE env). */
80
84
  handle?: string;
85
+ /** @deprecated Prefer FORGE_API_KEY env — per-project key from Forge dashboard. */
81
86
  registerSecret?: string;
82
- /** Merchant public base URL for fulfillment. */
87
+ /** Merchant public base URL. Usually omitted — resolved automatically. */
83
88
  publicBaseUrl?: string;
84
89
  };
85
90
  /**
@@ -103,6 +108,7 @@ declare function defineAgentService<TInput extends Record<string, unknown> = Rec
103
108
 
104
109
  /**
105
110
  * Mount Forge agent services on an Express app.
111
+ * - GET /forge/health, GET /forge/status, GET /.well-known/clawcash.json — liveliness
106
112
  * - POST {basePath}/{kebab-name} — optional public x402 agent surface
107
113
  * - POST /forge/fulfill/{kebab-name} — private gateway fulfillment after payment
108
114
  *
@@ -133,6 +139,42 @@ declare function resolvePayTo(opts: {
133
139
  timeoutMs?: number;
134
140
  }): Promise<string>;
135
141
 
142
+ /**
143
+ * Public base URL resolution, in trust order:
144
+ * 1. PUBLIC_BASE_URL env — explicit override.
145
+ * 2. Platform-provided vars (Railway, Render, Vercel, Fly, Heroku) — set by
146
+ * the host, not by request input, so safe to trust as-is.
147
+ * 3. Lazy inference from the first inbound request to the Forge surface
148
+ * (X-Forwarded-Proto + Host). Host is attacker-controlled, so a candidate
149
+ * is only accepted after self-verification: we fetch our own
150
+ * /forge/health at the candidate URL and check it returns this
151
+ * instance's boot nonce.
152
+ */
153
+ declare function resolveBaseUrlFromEnv(explicit?: string): string | null;
154
+ declare class PublicBaseUrlResolver {
155
+ /** Per-boot nonce, echoed by /forge/health for self-verification. */
156
+ readonly instanceNonce: string;
157
+ private resolved;
158
+ private verifying;
159
+ private rejected;
160
+ private attempts;
161
+ private onResolved;
162
+ constructor(opts: {
163
+ /** URL already known from env/platform vars (trusted, no verification). */
164
+ initial: string | null;
165
+ /** Called once when a base URL first becomes known via inference. */
166
+ onResolved?: (baseUrl: string) => void;
167
+ });
168
+ get(): string | null;
169
+ /**
170
+ * Feed an inbound Forge-surface request. No-op once resolved. Kicks off
171
+ * async self-verification of the candidate URL derived from the request.
172
+ */
173
+ considerRequest(req: Request): void;
174
+ /** Fetch our own /forge/health at the candidate and match the boot nonce. */
175
+ private verify;
176
+ }
177
+
136
178
  /**
137
179
  * Notify ClawCash gateway of this merchant's live public base URL.
138
180
  * Full action registration still happens from Forge "Go live".
@@ -145,9 +187,82 @@ declare function heartbeatGateway(opts: {
145
187
  }): Promise<void>;
146
188
 
147
189
  /**
148
- * Shared secret auth for ClawCash gateway merchant fulfillment.
149
- * Same secret as GATEWAY_REGISTER_SECRET (Forge go-live / heartbeat).
190
+ * Merchant-side Forge surface status — public probes for deploy / go-live checks.
191
+ */
192
+ type ForgeHeartbeatState = {
193
+ attempted: boolean;
194
+ ok: boolean | null;
195
+ at: string | null;
196
+ error: string | null;
197
+ };
198
+ type ForgeSurfaceStatus = {
199
+ ok: boolean;
200
+ forge: true;
201
+ version: string;
202
+ handle: string | null;
203
+ publicBaseUrl: string | null;
204
+ gatewayUrl: string | null;
205
+ /** True when FORGE_API_KEY is set so /forge/fulfill is mounted. */
206
+ fulfillMounted: boolean;
207
+ fulfillPath: string;
208
+ agentBasePath: string;
209
+ skipPayment: boolean;
210
+ actions: Array<{
211
+ name: string;
212
+ path: string;
213
+ price: string;
214
+ }>;
215
+ /** Env + fulfill ready — merchant can accept gateway fulfillment. */
216
+ ready: boolean;
217
+ heartbeat: ForgeHeartbeatState;
218
+ endpoints: {
219
+ health: string;
220
+ status: string;
221
+ wellKnown: string;
222
+ fulfill: string;
223
+ agent: string;
224
+ };
225
+ };
226
+ declare function recordHeartbeatResult(result: {
227
+ ok: true;
228
+ } | {
229
+ ok: false;
230
+ error: string;
231
+ }): void;
232
+ declare function getLastHeartbeat(): ForgeHeartbeatState;
233
+ declare function buildForgeSurfaceStatus(opts: {
234
+ handle: string | null;
235
+ publicBaseUrl: string | null;
236
+ gatewayUrl: string | null;
237
+ fulfillMounted: boolean;
238
+ fulfillPath: string;
239
+ agentBasePath: string;
240
+ skipPayment: boolean;
241
+ actions: Array<{
242
+ name: string;
243
+ path: string;
244
+ price: string;
245
+ }>;
246
+ }): ForgeSurfaceStatus;
247
+ declare function buildWellKnownDocument(status: ForgeSurfaceStatus): {
248
+ forge: true;
249
+ version: string;
250
+ health: string;
251
+ status: string;
252
+ handle: string | null;
253
+ ready: boolean;
254
+ };
255
+ declare function forgeSdkVersion(): string;
256
+
257
+ /**
258
+ * Per-project Forge API key for gateway → merchant fulfillment.
259
+ * Merchants set FORGE_API_KEY from the Forge dashboard (never the shared
260
+ * GATEWAY_REGISTER_SECRET — that is Forge↔gateway platform auth only).
261
+ *
262
+ * GATEWAY_REGISTER_SECRET is accepted as a deprecated fallback for older deploys.
150
263
  */
264
+ declare function getForgeApiKey(explicit?: string | null): string | null;
265
+ /** @deprecated Use getForgeApiKey */
151
266
  declare function getForgeGatewaySecret(explicit?: string | null): string | null;
152
267
  declare function isForgeGatewayRequest(req: Request, secret?: string | null): boolean;
153
268
  /** Synthetic user id for DB rows created by gateway-driven fulfillment. */
@@ -156,4 +271,4 @@ declare function requireForgeGateway(secret?: string | null): (req: Request, res
156
271
  /** Headers merchant execute() should send on loopback calls during fulfillment. */
157
272
  declare function forgeGatewayLoopbackHeaders(secret?: string | null): Record<string, string>;
158
273
 
159
- export { type AgentServiceConfig, type AgentServiceContext, type DefinedAgentService, FORGE_GATEWAY_USER_ID, type ForgePayToSource, type InputSchema, type MountOptions, type OutputSchema, type PaymentConfig, type SchemaFieldType, type SkillMeta, type WaitUntilOptions, createContext, createForgeRouter, defineAgentService, forgeGatewayLoopbackHeaders, generateSkillMarkdown, getForgeGatewaySecret, heartbeatGateway, isForgeGatewayRequest, isZeroAddress, mountAgentServices, requireForgeGateway, resolvePayTo, toKebabCase, waitUntil };
274
+ export { type AgentServiceConfig, type AgentServiceContext, type DefinedAgentService, FORGE_GATEWAY_USER_ID, type ForgeHeartbeatState, type ForgePayToSource, type ForgeSurfaceStatus, type InputSchema, type MountOptions, type OutputSchema, type PaymentConfig, PublicBaseUrlResolver, type SchemaFieldType, type SkillMeta, type WaitUntilOptions, buildForgeSurfaceStatus, buildWellKnownDocument, createContext, createForgeRouter, defineAgentService, forgeGatewayLoopbackHeaders, forgeSdkVersion, generateSkillMarkdown, getForgeApiKey, getForgeGatewaySecret, getLastHeartbeat, heartbeatGateway, isForgeGatewayRequest, isZeroAddress, mountAgentServices, recordHeartbeatResult, requireForgeGateway, resolveBaseUrlFromEnv, resolvePayTo, toKebabCase, waitUntil };