@nordsym/apiclaw 2.1.0 → 2.2.1
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 +15 -2
- package/dist/bin-http.js +0 -0
- package/dist/bin.bundled.js +79288 -0
- package/dist/funnel-client.d.ts +24 -0
- package/dist/funnel-client.d.ts.map +1 -0
- package/dist/funnel-client.js +131 -0
- package/dist/funnel-client.js.map +1 -0
- package/dist/funnel.test.d.ts +2 -0
- package/dist/funnel.test.d.ts.map +1 -0
- package/dist/funnel.test.js +145 -0
- package/dist/funnel.test.js.map +1 -0
- package/dist/gateway-client.d.ts.map +1 -1
- package/dist/gateway-client.js +24 -2
- package/dist/gateway-client.js.map +1 -1
- package/dist/index.bundled.js +61263 -0
- package/dist/index.js +161 -74
- package/dist/index.js.map +1 -1
- package/dist/postinstall.d.ts +0 -5
- package/dist/postinstall.d.ts.map +1 -1
- package/dist/postinstall.js +24 -3
- package/dist/postinstall.js.map +1 -1
- package/dist/registration-guard.d.ts +29 -0
- package/dist/registration-guard.d.ts.map +1 -0
- package/dist/registration-guard.js +87 -0
- package/dist/registration-guard.js.map +1 -0
- package/package.json +7 -2
- package/.claude/settings.local.json +0 -9
- package/.env.prod +0 -1
- package/apiclaw-README.md +0 -494
- package/convex/_generated/api.d.ts +0 -137
- package/convex/_generated/api.js +0 -23
- package/convex/_generated/dataModel.d.ts +0 -60
- package/convex/_generated/server.d.ts +0 -143
- package/convex/_generated/server.js +0 -93
- package/convex/adminActivate.ts +0 -53
- package/convex/adminStats.ts +0 -306
- package/convex/agents.ts +0 -939
- package/convex/analytics.ts +0 -187
- package/convex/apiKeys.ts +0 -220
- package/convex/backfillAnalytics.ts +0 -272
- package/convex/backfillSearchLogs.ts +0 -35
- package/convex/billing.ts +0 -834
- package/convex/capabilities.ts +0 -157
- package/convex/chains.ts +0 -1318
- package/convex/credits.ts +0 -211
- package/convex/crons.ts +0 -50
- package/convex/debugFilestackLogs.ts +0 -16
- package/convex/debugGetToken.ts +0 -18
- package/convex/directCall.ts +0 -713
- package/convex/earnProgress.ts +0 -753
- package/convex/email.ts +0 -329
- package/convex/feedback.ts +0 -265
- package/convex/http.ts +0 -3430
- package/convex/inbound.ts +0 -32
- package/convex/logs.ts +0 -701
- package/convex/migrateFilestack.ts +0 -81
- package/convex/migratePartnersProd.ts +0 -174
- package/convex/migratePratham.ts +0 -126
- package/convex/migrateProviderWorkspaces.ts +0 -175
- package/convex/mou.ts +0 -91
- package/convex/providerKeys.ts +0 -289
- package/convex/providers.ts +0 -1135
- package/convex/purchases.ts +0 -183
- package/convex/ratelimit.ts +0 -104
- package/convex/schema.ts +0 -869
- package/convex/searchLogs.ts +0 -265
- package/convex/seedAPILayerAPIs.ts +0 -191
- package/convex/seedDirectCallConfigs.ts +0 -336
- package/convex/seedPratham.ts +0 -149
- package/convex/spendAlerts.ts +0 -442
- package/convex/stripeActions.ts +0 -607
- package/convex/teams.ts +0 -243
- package/convex/telemetry.ts +0 -81
- package/convex/tsconfig.json +0 -25
- package/convex/updateAPIStatus.ts +0 -44
- package/convex/usage.ts +0 -260
- package/convex/usageReports.ts +0 -357
- package/convex/waitlist.ts +0 -55
- package/convex/webhooks.ts +0 -494
- package/convex/workspaceSettings.ts +0 -143
- package/convex/workspaces.ts +0 -1331
- package/convex.json +0 -3
- package/direct-test.mjs +0 -51
- package/email-templates/filestack-provider-outreach.html +0 -162
- package/email-templates/partnership-template.html +0 -116
- package/email-templates/pratham-draft-preview.txt +0 -57
- package/email-templates/pratham-partnership-draft.html +0 -141
- package/reports/APIClaw-Session-Report-2026-04-05.pdf +0 -0
- package/reports/pipeline/PIPELINE-REPORT.json +0 -153
- package/reports/pipeline/acquire_apisguru.json +0 -17
- package/reports/pipeline/capabilities.json +0 -38
- package/reports/pipeline/discover_azure_recursive.json +0 -1551
- package/reports/pipeline/discover_github.json +0 -25
- package/reports/pipeline/discover_github_repos.json +0 -49
- package/reports/pipeline/discover_swaggerhub.json +0 -24
- package/reports/pipeline/discover_well_known.json +0 -23
- package/reports/pipeline/fetch_specs.json +0 -19
- package/reports/pipeline/generate_providers.json +0 -14
- package/reports/pipeline/match_registry.json +0 -11
- package/reports/pipeline/parse_specs.json +0 -17
- package/reports/pipeline/promote_candidates.json +0 -34
- package/reports/pipeline/validate.json +0 -30
- package/reports/pipeline/validate_smoke_details.json +0 -3835
- package/reports/session-report-2026-04-05.html +0 -433
- package/seed-apis-direct.mjs +0 -106
- package/src/access-control.ts +0 -174
- package/src/adapters/base.ts +0 -364
- package/src/adapters/claude-desktop.ts +0 -41
- package/src/adapters/cline.ts +0 -88
- package/src/adapters/continue.ts +0 -91
- package/src/adapters/cursor.ts +0 -43
- package/src/adapters/custom.ts +0 -188
- package/src/adapters/detect.ts +0 -202
- package/src/adapters/index.ts +0 -47
- package/src/adapters/windsurf.ts +0 -44
- package/src/bin-http.ts +0 -45
- package/src/bin.ts +0 -34
- package/src/capability-router.ts +0 -331
- package/src/chainExecutor.ts +0 -730
- package/src/chainResolver.test.ts +0 -246
- package/src/chainResolver.ts +0 -658
- package/src/cli/commands/demo.ts +0 -109
- package/src/cli/commands/doctor.ts +0 -435
- package/src/cli/commands/index.ts +0 -9
- package/src/cli/commands/login.ts +0 -203
- package/src/cli/commands/mcp-install.ts +0 -373
- package/src/cli/commands/restore.ts +0 -333
- package/src/cli/commands/setup.ts +0 -297
- package/src/cli/commands/uninstall.ts +0 -240
- package/src/cli/index.ts +0 -148
- package/src/cli.ts +0 -370
- package/src/confirmation.ts +0 -296
- package/src/credentials.ts +0 -455
- package/src/credits.ts +0 -329
- package/src/crypto.ts +0 -75
- package/src/discovery.ts +0 -568
- package/src/enterprise/env.ts +0 -156
- package/src/enterprise/index.ts +0 -7
- package/src/enterprise/script-generator.ts +0 -481
- package/src/execute-dynamic.ts +0 -617
- package/src/execute.ts +0 -2386
- package/src/gateway-client.ts +0 -192
- package/src/hivr-whitelist.ts +0 -110
- package/src/http-api.ts +0 -286
- package/src/http-server-minimal.ts +0 -154
- package/src/index.ts +0 -2611
- package/src/intelligent-gateway.ts +0 -339
- package/src/mcp-analytics.ts +0 -156
- package/src/metered.ts +0 -149
- package/src/open-apis-generated.ts +0 -157
- package/src/open-apis.ts +0 -558
- package/src/postinstall.ts +0 -18
- package/src/product-whitelist.ts +0 -246
- package/src/proxy.ts +0 -36
- package/src/session.ts +0 -129
- package/src/stripe.ts +0 -497
- package/src/telemetry.ts +0 -71
- package/src/test.ts +0 -135
- package/src/types/convex-api.d.ts +0 -20
- package/src/types/convex-api.ts +0 -21
- package/src/types.ts +0 -109
- package/src/ui/colors.ts +0 -219
- package/src/ui/errors.ts +0 -394
- package/src/ui/index.ts +0 -17
- package/src/ui/prompts.ts +0 -390
- package/src/ui/spinner.ts +0 -325
- package/src/utils/backup.ts +0 -224
- package/src/utils/config.ts +0 -318
- package/src/utils/os.ts +0 -124
- package/src/utils/paths.ts +0 -203
- package/src/webhook.ts +0 -107
- package/test-10-working.cjs +0 -97
- package/test-14-final.cjs +0 -96
- package/test-actual-handlers.ts +0 -92
- package/test-apilayer-all-14.ts +0 -249
- package/test-apilayer-fixed.ts +0 -248
- package/test-direct-endpoints.ts +0 -174
- package/test-exact-endpoints.ts +0 -144
- package/test-final.ts +0 -83
- package/test-full-routing.ts +0 -100
- package/test-handlers-correct.ts +0 -217
- package/test-numverify-key.ts +0 -41
- package/test-via-handlers.ts +0 -92
- package/test-worldnews.mjs +0 -26
- package/tsconfig.json +0 -20
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type FunnelEventName = "install" | "first_run" | "register_owner" | "verify_code" | "first_call_api_success" | "register_owner_failed" | "verify_code_failed" | "call_api_blocked" | "call_api_error" | "quota_hit" | "gateway_retry";
|
|
2
|
+
export type Classification = "human" | "ci" | "bot" | "internal";
|
|
3
|
+
export declare function classifyLocalSource(input: {
|
|
4
|
+
userAgent?: string | null;
|
|
5
|
+
email?: string | null;
|
|
6
|
+
fingerprint?: string | null;
|
|
7
|
+
env?: NodeJS.ProcessEnv;
|
|
8
|
+
}): Classification;
|
|
9
|
+
export declare function hasLocalMarker(key: string): boolean;
|
|
10
|
+
export declare function setLocalMarker(key: string): void;
|
|
11
|
+
export interface EmitArgs {
|
|
12
|
+
event: FunnelEventName;
|
|
13
|
+
workspaceId?: string;
|
|
14
|
+
fingerprint?: string;
|
|
15
|
+
sessionToken?: string;
|
|
16
|
+
email?: string;
|
|
17
|
+
mcpClient?: string;
|
|
18
|
+
platform?: string;
|
|
19
|
+
version?: string;
|
|
20
|
+
dedupeKey?: string;
|
|
21
|
+
props?: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
export declare function emitFunnelEvent(args: EmitArgs): void;
|
|
24
|
+
//# sourceMappingURL=funnel-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnel-client.d.ts","sourceRoot":"","sources":["../src/funnel-client.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,WAAW,GACX,gBAAgB,GAChB,aAAa,GACb,wBAAwB,GAExB,uBAAuB,GACvB,oBAAoB,GACpB,kBAAkB,GAClB,gBAAgB,GAChB,WAAW,GACX,eAAe,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,UAAU,CAAC;AAkCjE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB,GAAG,cAAc,CAmBjB;AAwBD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAIhD;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,eAAe,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAoCpD"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* APIClaw Funnel — client-side emitter for MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Fire-and-forget POST to Convex funnel:recordEvent. Never throws, never
|
|
5
|
+
* blocks. See convex/funnel.ts for schema and classification rules.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "fs";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
import * as os from "os";
|
|
10
|
+
const CONVEX_URL = process.env.CONVEX_URL || "https://adventurous-avocet-799.convex.cloud";
|
|
11
|
+
const CI_ENV_KEYS = [
|
|
12
|
+
"CI",
|
|
13
|
+
"GITHUB_ACTIONS",
|
|
14
|
+
"GITLAB_CI",
|
|
15
|
+
"CIRCLECI",
|
|
16
|
+
"BUILDKITE",
|
|
17
|
+
"JENKINS_URL",
|
|
18
|
+
"TEAMCITY_VERSION",
|
|
19
|
+
"TRAVIS",
|
|
20
|
+
"BITBUCKET_BUILD_NUMBER",
|
|
21
|
+
];
|
|
22
|
+
const BOT_UA_MARKERS = [
|
|
23
|
+
"bot",
|
|
24
|
+
"crawl",
|
|
25
|
+
"spider",
|
|
26
|
+
"scanner",
|
|
27
|
+
"curl/",
|
|
28
|
+
"wget/",
|
|
29
|
+
"httpclient",
|
|
30
|
+
"python-requests",
|
|
31
|
+
"go-http-client",
|
|
32
|
+
"okhttp",
|
|
33
|
+
"java/",
|
|
34
|
+
"httrack",
|
|
35
|
+
"headlesschrome",
|
|
36
|
+
"phantomjs",
|
|
37
|
+
];
|
|
38
|
+
const INTERNAL_EMAIL_DOMAINS = ["nordsym.com", "apiclaw.cloud"];
|
|
39
|
+
const INTERNAL_EMAIL_EXACT = ["gustav@nordsym.com", "gustavnordsync@gmail.com"];
|
|
40
|
+
export function classifyLocalSource(input) {
|
|
41
|
+
const email = (input.email || "").toLowerCase().trim();
|
|
42
|
+
if (email) {
|
|
43
|
+
if (INTERNAL_EMAIL_EXACT.includes(email))
|
|
44
|
+
return "internal";
|
|
45
|
+
const domain = email.split("@")[1] || "";
|
|
46
|
+
if (INTERNAL_EMAIL_DOMAINS.includes(domain))
|
|
47
|
+
return "internal";
|
|
48
|
+
}
|
|
49
|
+
const env = input.env || process.env;
|
|
50
|
+
for (const key of CI_ENV_KEYS) {
|
|
51
|
+
const val = env[key];
|
|
52
|
+
if (val && val !== "false" && val !== "0")
|
|
53
|
+
return "ci";
|
|
54
|
+
}
|
|
55
|
+
const ua = (input.userAgent || "").toLowerCase();
|
|
56
|
+
if (ua) {
|
|
57
|
+
for (const m of BOT_UA_MARKERS) {
|
|
58
|
+
if (ua.includes(m))
|
|
59
|
+
return "bot";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return "human";
|
|
63
|
+
}
|
|
64
|
+
// Persistent first-run marker stored alongside the session file.
|
|
65
|
+
const MARKER_DIR = path.join(os.homedir(), ".apiclaw");
|
|
66
|
+
const MARKER_FILE = path.join(MARKER_DIR, "funnel-markers.json");
|
|
67
|
+
function readMarkers() {
|
|
68
|
+
try {
|
|
69
|
+
if (!fs.existsSync(MARKER_FILE))
|
|
70
|
+
return {};
|
|
71
|
+
return JSON.parse(fs.readFileSync(MARKER_FILE, "utf8")) || {};
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return {};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function writeMarkers(m) {
|
|
78
|
+
try {
|
|
79
|
+
if (!fs.existsSync(MARKER_DIR))
|
|
80
|
+
fs.mkdirSync(MARKER_DIR, { mode: 0o700 });
|
|
81
|
+
fs.writeFileSync(MARKER_FILE, JSON.stringify(m), { mode: 0o600 });
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
/* ignore */
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export function hasLocalMarker(key) {
|
|
88
|
+
return !!readMarkers()[key];
|
|
89
|
+
}
|
|
90
|
+
export function setLocalMarker(key) {
|
|
91
|
+
const m = readMarkers();
|
|
92
|
+
m[key] = Date.now();
|
|
93
|
+
writeMarkers(m);
|
|
94
|
+
}
|
|
95
|
+
export function emitFunnelEvent(args) {
|
|
96
|
+
if (process.env.APICLAW_TELEMETRY === "false")
|
|
97
|
+
return;
|
|
98
|
+
const classification = classifyLocalSource({
|
|
99
|
+
email: args.email,
|
|
100
|
+
fingerprint: args.fingerprint,
|
|
101
|
+
});
|
|
102
|
+
const payload = {
|
|
103
|
+
path: "funnel:recordEvent",
|
|
104
|
+
args: {
|
|
105
|
+
event: args.event,
|
|
106
|
+
classification,
|
|
107
|
+
workspaceId: args.workspaceId,
|
|
108
|
+
fingerprint: args.fingerprint,
|
|
109
|
+
sessionToken: args.sessionToken,
|
|
110
|
+
email: args.email,
|
|
111
|
+
userAgent: `apiclaw-mcp/${args.version || "unknown"}`,
|
|
112
|
+
mcpClient: args.mcpClient,
|
|
113
|
+
platform: args.platform || process.platform,
|
|
114
|
+
version: args.version,
|
|
115
|
+
dedupeKey: args.dedupeKey,
|
|
116
|
+
props: args.props,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
// Fire and forget.
|
|
120
|
+
try {
|
|
121
|
+
fetch(`${CONVEX_URL}/api/mutation`, {
|
|
122
|
+
method: "POST",
|
|
123
|
+
headers: { "Content-Type": "application/json" },
|
|
124
|
+
body: JSON.stringify(payload),
|
|
125
|
+
}).catch(() => { });
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
/* ignore */
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=funnel-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnel-client.js","sourceRoot":"","sources":["../src/funnel-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnel.test.d.ts","sourceRoot":"","sources":["../src/funnel.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for funnel classification + registration guard + event canon.
|
|
3
|
+
* Run: npx tsx src/funnel.test.ts
|
|
4
|
+
*/
|
|
5
|
+
import { strict as assert } from 'node:assert';
|
|
6
|
+
import { classifyLocalSource } from './funnel-client.js';
|
|
7
|
+
import { requireVerifiedOwner, FREE_CALL_PATHS, ENFORCED_CALL_PATHS, } from './registration-guard.js';
|
|
8
|
+
let failed = 0;
|
|
9
|
+
let passed = 0;
|
|
10
|
+
function test(name, fn) {
|
|
11
|
+
try {
|
|
12
|
+
fn();
|
|
13
|
+
console.log(`✅ ${name}`);
|
|
14
|
+
passed++;
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
console.log(`❌ ${name}`);
|
|
18
|
+
console.log(` ${e.message || e}`);
|
|
19
|
+
failed++;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// ------------------------------------------------------------------
|
|
23
|
+
// Classification
|
|
24
|
+
// ------------------------------------------------------------------
|
|
25
|
+
test('classify: human is default', () => {
|
|
26
|
+
assert.equal(classifyLocalSource({ env: {} }), 'human');
|
|
27
|
+
});
|
|
28
|
+
test('classify: CI env flag → ci', () => {
|
|
29
|
+
assert.equal(classifyLocalSource({ env: { CI: 'true' } }), 'ci');
|
|
30
|
+
assert.equal(classifyLocalSource({ env: { GITHUB_ACTIONS: '1' } }), 'ci');
|
|
31
|
+
assert.equal(classifyLocalSource({ env: { CIRCLECI: 'true' } }), 'ci');
|
|
32
|
+
});
|
|
33
|
+
test('classify: CI=false is NOT ci', () => {
|
|
34
|
+
assert.equal(classifyLocalSource({ env: { CI: 'false' } }), 'human');
|
|
35
|
+
assert.equal(classifyLocalSource({ env: { CI: '0' } }), 'human');
|
|
36
|
+
});
|
|
37
|
+
test('classify: bot UA → bot', () => {
|
|
38
|
+
assert.equal(classifyLocalSource({ env: {}, userAgent: 'curl/7.88' }), 'bot');
|
|
39
|
+
assert.equal(classifyLocalSource({ env: {}, userAgent: 'Mozilla/5.0 (compatible; Googlebot/2.1)' }), 'bot');
|
|
40
|
+
assert.equal(classifyLocalSource({ env: {}, userAgent: 'python-requests/2.31' }), 'bot');
|
|
41
|
+
});
|
|
42
|
+
test('classify: internal email domain → internal', () => {
|
|
43
|
+
assert.equal(classifyLocalSource({ env: {}, email: 'someone@nordsym.com' }), 'internal');
|
|
44
|
+
assert.equal(classifyLocalSource({ env: {}, email: 'test@apiclaw.cloud' }), 'internal');
|
|
45
|
+
});
|
|
46
|
+
test('classify: internal exact email → internal (even with CI set)', () => {
|
|
47
|
+
assert.equal(classifyLocalSource({
|
|
48
|
+
env: { CI: 'true' },
|
|
49
|
+
email: 'gustavnordsync@gmail.com',
|
|
50
|
+
}), 'internal');
|
|
51
|
+
});
|
|
52
|
+
test('classify: precedence internal > ci > bot > human', () => {
|
|
53
|
+
// internal wins over CI
|
|
54
|
+
assert.equal(classifyLocalSource({ env: { CI: 'true' }, email: 'x@nordsym.com' }), 'internal');
|
|
55
|
+
// ci wins over bot
|
|
56
|
+
assert.equal(classifyLocalSource({ env: { CI: 'true' }, userAgent: 'curl/8' }), 'ci');
|
|
57
|
+
});
|
|
58
|
+
// ------------------------------------------------------------------
|
|
59
|
+
// requireVerifiedOwner
|
|
60
|
+
// ------------------------------------------------------------------
|
|
61
|
+
const good = {
|
|
62
|
+
sessionToken: 'tok',
|
|
63
|
+
workspaceId: 'ws_1',
|
|
64
|
+
email: 'user@example.com',
|
|
65
|
+
tier: 'free',
|
|
66
|
+
status: 'active',
|
|
67
|
+
usageRemaining: 42,
|
|
68
|
+
usageCount: 8,
|
|
69
|
+
};
|
|
70
|
+
test('guard: no workspace → no_session', () => {
|
|
71
|
+
const r = requireVerifiedOwner(null);
|
|
72
|
+
assert.equal(r.ok, false);
|
|
73
|
+
if (!r.ok)
|
|
74
|
+
assert.equal(r.reason, 'no_session');
|
|
75
|
+
});
|
|
76
|
+
test('guard: workspace without email → pending_verification', () => {
|
|
77
|
+
const r = requireVerifiedOwner({ ...good, email: '' });
|
|
78
|
+
assert.equal(r.ok, false);
|
|
79
|
+
if (!r.ok)
|
|
80
|
+
assert.equal(r.reason, 'pending_verification');
|
|
81
|
+
});
|
|
82
|
+
test('guard: workspace status pending → not_verified', () => {
|
|
83
|
+
const r = requireVerifiedOwner({ ...good, status: 'pending' });
|
|
84
|
+
assert.equal(r.ok, false);
|
|
85
|
+
if (!r.ok)
|
|
86
|
+
assert.equal(r.reason, 'not_verified');
|
|
87
|
+
});
|
|
88
|
+
test('guard: quota exhausted → quota_exceeded', () => {
|
|
89
|
+
const r = requireVerifiedOwner({ ...good, usageRemaining: 0 });
|
|
90
|
+
assert.equal(r.ok, false);
|
|
91
|
+
if (!r.ok)
|
|
92
|
+
assert.equal(r.reason, 'quota_exceeded');
|
|
93
|
+
});
|
|
94
|
+
test('guard: happy path → ok', () => {
|
|
95
|
+
const r = requireVerifiedOwner(good);
|
|
96
|
+
assert.equal(r.ok, true);
|
|
97
|
+
if (r.ok)
|
|
98
|
+
assert.equal(r.ctx.email, 'user@example.com');
|
|
99
|
+
});
|
|
100
|
+
test('guard: unlimited (usageRemaining=-1) → ok', () => {
|
|
101
|
+
const r = requireVerifiedOwner({ ...good, usageRemaining: -1 });
|
|
102
|
+
assert.equal(r.ok, true);
|
|
103
|
+
});
|
|
104
|
+
// ------------------------------------------------------------------
|
|
105
|
+
// Enforcement matrix coverage
|
|
106
|
+
// ------------------------------------------------------------------
|
|
107
|
+
test('matrix: discover_apis is free', () => {
|
|
108
|
+
assert.equal(FREE_CALL_PATHS.has('discover_apis'), true);
|
|
109
|
+
assert.equal(ENFORCED_CALL_PATHS.has('discover_apis'), false);
|
|
110
|
+
});
|
|
111
|
+
test('matrix: call_api / capability / resume_chain are enforced', () => {
|
|
112
|
+
for (const p of ['call_api', 'capability', 'resume_chain']) {
|
|
113
|
+
assert.equal(ENFORCED_CALL_PATHS.has(p), true, `${p} should be enforced`);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
test('matrix: register_owner + verify_code are free (they BECOME the auth)', () => {
|
|
117
|
+
assert.equal(FREE_CALL_PATHS.has('register_owner'), true);
|
|
118
|
+
assert.equal(FREE_CALL_PATHS.has('verify_code'), true);
|
|
119
|
+
});
|
|
120
|
+
test('matrix: free and enforced sets are disjoint', () => {
|
|
121
|
+
for (const p of FREE_CALL_PATHS) {
|
|
122
|
+
assert.equal(ENFORCED_CALL_PATHS.has(p), false, `${p} is in both sets`);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
test('event canon: all 11 approved events are typed', () => {
|
|
126
|
+
const names = [
|
|
127
|
+
'install',
|
|
128
|
+
'first_run',
|
|
129
|
+
'register_owner',
|
|
130
|
+
'verify_code',
|
|
131
|
+
'first_call_api_success',
|
|
132
|
+
'register_owner_failed',
|
|
133
|
+
'verify_code_failed',
|
|
134
|
+
'call_api_blocked',
|
|
135
|
+
'call_api_error',
|
|
136
|
+
'quota_hit',
|
|
137
|
+
'gateway_retry',
|
|
138
|
+
];
|
|
139
|
+
assert.equal(names.length, 11);
|
|
140
|
+
});
|
|
141
|
+
console.log('');
|
|
142
|
+
console.log(`Results: ${passed} passed, ${failed} failed`);
|
|
143
|
+
if (failed > 0)
|
|
144
|
+
process.exit(1);
|
|
145
|
+
//# sourceMappingURL=funnel.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnel.test.js","sourceRoot":"","sources":["../src/funnel.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-client.d.ts","sourceRoot":"","sources":["../src/gateway-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"gateway-client.d.ts","sourceRoot":"","sources":["../src/gateway-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA2BD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAI1C;AASD,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAS;;IAOzB,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,eAAe,CAAC;IAoF3B;;OAEG;YACW,OAAO;CAsBtB;AAKD,wBAAgB,UAAU,IAAI,aAAa,CAG1C"}
|
package/dist/gateway-client.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { readFileSync } from 'fs';
|
|
8
8
|
import { join } from 'path';
|
|
9
9
|
import { homedir } from 'os';
|
|
10
|
+
import { emitFunnelEvent } from './funnel-client.js';
|
|
10
11
|
// ---------------------------------------------------------------------------
|
|
11
12
|
// Secret resolution
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
@@ -66,11 +67,32 @@ export class GatewayClient {
|
|
|
66
67
|
const body = JSON.stringify({ provider, action, params });
|
|
67
68
|
// First attempt
|
|
68
69
|
let response = await this.doFetch(url, headers, body);
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
let firstStatus = response?.status ?? null;
|
|
71
|
+
// Retry once on network error OR 5xx
|
|
72
|
+
if (!response || response.status >= 500) {
|
|
73
|
+
const reason = !response ? 'fetch_fail' : `5xx:${response.status}`;
|
|
74
|
+
emitFunnelEvent({
|
|
75
|
+
event: 'gateway_retry',
|
|
76
|
+
workspaceId: options?.workspaceId,
|
|
77
|
+
version: process.env.npm_package_version || 'unknown',
|
|
78
|
+
props: { attempt: 2, reason, provider, action },
|
|
79
|
+
});
|
|
80
|
+
// If first response was a 5xx, drain it before retry
|
|
81
|
+
if (response && response.status >= 500) {
|
|
82
|
+
try {
|
|
83
|
+
await response.text();
|
|
84
|
+
}
|
|
85
|
+
catch { /* ignore */ }
|
|
86
|
+
}
|
|
71
87
|
response = await this.doFetch(url, headers, body);
|
|
72
88
|
}
|
|
73
89
|
if (!response) {
|
|
90
|
+
emitFunnelEvent({
|
|
91
|
+
event: 'gateway_retry',
|
|
92
|
+
workspaceId: options?.workspaceId,
|
|
93
|
+
version: process.env.npm_package_version || 'unknown',
|
|
94
|
+
props: { attempt: 2, reason: 'retry_exhausted', provider, action, firstStatus },
|
|
95
|
+
});
|
|
74
96
|
return {
|
|
75
97
|
success: false,
|
|
76
98
|
provider,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-client.js","sourceRoot":"","sources":["../src/gateway-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway-client.js","sourceRoot":"","sources":["../src/gateway-client.ts"],"names":[],"mappings":"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"}
|