@maxceem/agw 0.7.2 → 0.8.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/dist/agw.mjs +130 -27
- package/package.json +2 -1
package/dist/agw.mjs
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// <define:__AGW_MANIFEST__>
|
|
9
|
-
var define_AGW_MANIFEST_default = { version: "0.
|
|
9
|
+
var define_AGW_MANIFEST_default = { version: "0.8.0", wrangler: "4.96.0", upgradeFrom: ["0.8.0", "0.7.2", "0.7.1", "0.7.0", "0.6.4", "0.6.3", "0.6.2", "0.6.1", "0.6.0", "0.5.2", "0.5.1", "0.5.0", "0.4.0"], release: { url: "https://github.com/maxceem/app-ai-gateway/releases/download/v0.8.0/gateway-0.8.0.tar.gz", sha256: "a9039b1c43d68bf0636e5492a4a2cccfa4b0229e61e790ae414174accc52f9c6", manifest: "eb3280cee275a74cf0ad39a25d20d2a0143be7f3be974f0f5635f4bf8aba0b0e" } };
|
|
10
10
|
|
|
11
11
|
// src/main.ts
|
|
12
12
|
import { Writable as Writable2 } from "node:stream";
|
|
@@ -15164,6 +15164,7 @@ var APP_STATUSES = ["active", "disabled"];
|
|
|
15164
15164
|
var ISSUER_PROVIDERS = ["firebase", "supabase", "auth0", "clerk", "custom"];
|
|
15165
15165
|
var ENTITLEMENT_CHECKS = ["revenuecat", "custom"];
|
|
15166
15166
|
var APP_ATTEST_ENVIRONMENTS = ["production", "development"];
|
|
15167
|
+
var APP_ATTEST_VERIFY_ON = ["every_request", "token_exchange"];
|
|
15167
15168
|
var ENDPOINT_SLUG = /^[a-z0-9-]{1,64}$/;
|
|
15168
15169
|
var PROVIDER_SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{0,62}$/;
|
|
15169
15170
|
var HTTP_FIELD_NAME = /^[A-Za-z0-9!#$%&'*+.^_`|~-]+$/;
|
|
@@ -15314,7 +15315,20 @@ var AppleAppAttestAuthenticationSchema = external_exports.object({
|
|
|
15314
15315
|
*/
|
|
15315
15316
|
environments: external_exports.array(external_exports.enum(APP_ATTEST_ENVIRONMENTS)).min(1, { error: "environments must name at least one environment" }).refine((values) => new Set(values).size === values.length, {
|
|
15316
15317
|
error: "environments cannot repeat a value"
|
|
15317
|
-
}).prefault(["production"])
|
|
15318
|
+
}).prefault(["production"]),
|
|
15319
|
+
/**
|
|
15320
|
+
* Where the install's App Attest key proves itself. `every_request`, the
|
|
15321
|
+
* default, binds every gateway request to the device: each one carries
|
|
15322
|
+
* an assertion over that very request, so a copied token is worthless.
|
|
15323
|
+
* `token_exchange` checks the assertion only when the hourly gateway
|
|
15324
|
+
* token is minted, and requests then carry the token alone; limits and
|
|
15325
|
+
* budgets still count per install, because the token names it.
|
|
15326
|
+
*/
|
|
15327
|
+
verify_on: external_exports.enum(APP_ATTEST_VERIFY_ON, {
|
|
15328
|
+
error: "verify_on must be one of every_request, token_exchange"
|
|
15329
|
+
}).default("every_request").meta({
|
|
15330
|
+
description: "When the install's App Attest assertion is verified. every_request (the default): every gateway request carries X-AppAttest-Proof, a fresh assertion over that request; needs the AppAIGateway Swift package 1.4 or later. token_exchange: the assertion is verified once, when the hourly gateway token is exchanged, and requests carry only the token."
|
|
15331
|
+
})
|
|
15318
15332
|
}).strict()
|
|
15319
15333
|
}).strict();
|
|
15320
15334
|
var ApiKeyAuthenticationSchema = external_exports.object({
|
|
@@ -15357,6 +15371,14 @@ var LimitScopeSchema = external_exports.object({
|
|
|
15357
15371
|
}).strict(),
|
|
15358
15372
|
spending: external_exports.object({ monthly_usd: NullableSpendLimit }).strict()
|
|
15359
15373
|
}).strict();
|
|
15374
|
+
var BUDGET_SCOPES = ["install", "user"];
|
|
15375
|
+
var PerUserLimitScopeSchema = LimitScopeSchema.extend({
|
|
15376
|
+
spending: LimitScopeSchema.shape.spending.extend({
|
|
15377
|
+
scope: external_exports.enum(BUDGET_SCOPES).optional().meta({
|
|
15378
|
+
description: "Whose month monthly_usd is measured over: install (the default on App Attest applications) or user (the default, and the only value, on server applications). user on an App Attest application needs authentication.end_user.source issuer. Filled in on every parsed configuration."
|
|
15379
|
+
})
|
|
15380
|
+
}).strict()
|
|
15381
|
+
}).strict();
|
|
15360
15382
|
var UNLIMITED_SCOPE = {
|
|
15361
15383
|
requests: { per_minute: null, per_day: null },
|
|
15362
15384
|
spending: { monthly_usd: null }
|
|
@@ -15395,7 +15417,7 @@ var AppConfigSchema = external_exports.object({
|
|
|
15395
15417
|
* parsed configuration: an unwritten block is the unlimited one.
|
|
15396
15418
|
*/
|
|
15397
15419
|
limits: external_exports.object({
|
|
15398
|
-
per_user:
|
|
15420
|
+
per_user: PerUserLimitScopeSchema.prefault(UNLIMITED_SCOPE),
|
|
15399
15421
|
per_app: LimitScopeSchema.prefault(UNLIMITED_SCOPE)
|
|
15400
15422
|
}).strict().prefault({}),
|
|
15401
15423
|
endpoints: external_exports.record(
|
|
@@ -15413,6 +15435,29 @@ var AppConfigSchema = external_exports.object({
|
|
|
15413
15435
|
message: "needs an authentication.end_user source other than none: this application identifies no end users, so use limits.per_app"
|
|
15414
15436
|
});
|
|
15415
15437
|
}
|
|
15438
|
+
const budgetScope = perUser?.spending.scope;
|
|
15439
|
+
if (authentication !== void 0 && budgetScope !== void 0) {
|
|
15440
|
+
if (authentication.type === "api_key" && budgetScope === "install") {
|
|
15441
|
+
context.addIssue({
|
|
15442
|
+
code: "custom",
|
|
15443
|
+
path: ["limits", "per_user", "spending", "scope"],
|
|
15444
|
+
message: "cannot be install: server applications have no install; the budget is per user"
|
|
15445
|
+
});
|
|
15446
|
+
}
|
|
15447
|
+
if (authentication.type === "apple_app_attest" && budgetScope === "user" && authentication.end_user.source !== "issuer") {
|
|
15448
|
+
context.addIssue({
|
|
15449
|
+
code: "custom",
|
|
15450
|
+
path: ["limits", "per_user", "spending", "scope"],
|
|
15451
|
+
message: "can be user only when authentication.end_user.source is issuer: under app_install every install is its own user, so use install"
|
|
15452
|
+
});
|
|
15453
|
+
}
|
|
15454
|
+
}
|
|
15455
|
+
}).overwrite((config2) => {
|
|
15456
|
+
const spending = config2.limits.per_user.spending;
|
|
15457
|
+
if (spending.scope === void 0) {
|
|
15458
|
+
spending.scope = config2.authentication.type === "apple_app_attest" ? "install" : "user";
|
|
15459
|
+
}
|
|
15460
|
+
return config2;
|
|
15416
15461
|
}).meta({ id: "AppConfig" });
|
|
15417
15462
|
var APP_ID_IS_SERVER_ASSIGNED = "id is assigned by the server: omit it and read app.id from the response";
|
|
15418
15463
|
var AppWriteSchema = external_exports.object({
|
|
@@ -15849,13 +15894,13 @@ var commands = {
|
|
|
15849
15894
|
"provider-gateway remove": { args: 1, flags: "yes!" },
|
|
15850
15895
|
"app add": {
|
|
15851
15896
|
args: 0,
|
|
15852
|
-
flags: "type name team-id bundle-id attest-environments provider* status file key-output dry-run!"
|
|
15897
|
+
flags: "type name team-id bundle-id attest-environments verify-on provider* status file key-output dry-run!"
|
|
15853
15898
|
},
|
|
15854
15899
|
"app list": { args: 0, flags: "" },
|
|
15855
15900
|
"app show": { args: 1, flags: "" },
|
|
15856
15901
|
"app update": {
|
|
15857
15902
|
args: 1,
|
|
15858
|
-
flags: "name team-id bundle-id attest-environments provider* all-providers! status file dry-run!"
|
|
15903
|
+
flags: "name team-id bundle-id attest-environments verify-on provider* all-providers! status file dry-run!"
|
|
15859
15904
|
},
|
|
15860
15905
|
"app validate": { args: 0, flags: "file" },
|
|
15861
15906
|
"app check": { args: 1, flags: "" },
|
|
@@ -16939,7 +16984,7 @@ async function appDocument(flags, current) {
|
|
|
16939
16984
|
if (!["ios", "server"].includes(type))
|
|
16940
16985
|
fail("invalid_input", "App type must be ios or server.");
|
|
16941
16986
|
const ios = type === "ios";
|
|
16942
|
-
if (!ios &&
|
|
16987
|
+
if (!ios && IOS_FLAGS.some((k) => flags[k]))
|
|
16943
16988
|
fail("invalid_input", "Server apps cannot use iOS flags.");
|
|
16944
16989
|
const bundle = ios ? await required2(flags, "bundle-id", "Apple bundle ID") : null;
|
|
16945
16990
|
doc = localApp({
|
|
@@ -16966,7 +17011,7 @@ async function appDocument(flags, current) {
|
|
|
16966
17011
|
if (flags.name) doc.name = flags.name;
|
|
16967
17012
|
if (flags.status) doc.status = flags.status === "disabled" ? "disabled" : "active";
|
|
16968
17013
|
const auth = doc.config.authentication;
|
|
16969
|
-
if (auth.type === "api_key" &&
|
|
17014
|
+
if (auth.type === "api_key" && IOS_FLAGS.some((k) => flags[k]))
|
|
16970
17015
|
fail("invalid_input", "Server apps cannot use iOS flags.");
|
|
16971
17016
|
if (auth.type === "apple_app_attest") {
|
|
16972
17017
|
if (flags["key-output"])
|
|
@@ -16975,6 +17020,8 @@ async function appDocument(flags, current) {
|
|
|
16975
17020
|
if (flags["bundle-id"]) auth.app_attest.bundle_id = flags["bundle-id"];
|
|
16976
17021
|
if (flags["attest-environments"])
|
|
16977
17022
|
auth.app_attest.environments = attestEnvironments(flags["attest-environments"]);
|
|
17023
|
+
if (flags["verify-on"])
|
|
17024
|
+
auth.app_attest.verify_on = flags["verify-on"].trim();
|
|
16978
17025
|
}
|
|
16979
17026
|
const selectedProviders = flagList(flags.provider);
|
|
16980
17027
|
if (selectedProviders.length) {
|
|
@@ -16989,6 +17036,7 @@ async function appDocument(flags, current) {
|
|
|
16989
17036
|
if (flags["all-providers"]) doc.config.routing.providers = { mode: "all" };
|
|
16990
17037
|
return localApp(doc);
|
|
16991
17038
|
}
|
|
17039
|
+
var IOS_FLAGS = ["team-id", "bundle-id", "attest-environments", "verify-on"];
|
|
16992
17040
|
function attestEnvironments(value) {
|
|
16993
17041
|
return value.split(",").map((name) => name.trim()).filter((name) => name.length > 0);
|
|
16994
17042
|
}
|
|
@@ -17074,7 +17122,7 @@ ${snippet}`;
|
|
|
17074
17122
|
...snippet ? { snippet } : {},
|
|
17075
17123
|
app: app2,
|
|
17076
17124
|
...key ? { applicationKey: key } : {},
|
|
17077
|
-
guidance: doc.config.authentication.type === "apple_app_attest" ? `Add https://github.com/maxceem/app-ai-gateway-swift from 1.
|
|
17125
|
+
guidance: doc.config.authentication.type === "apple_app_attest" ? `Add https://github.com/maxceem/app-ai-gateway-swift from 1.4.0, enable App Attest, and test on a supported physical device. Run agw app snippet ${app2.id} --provider <slug> for integration code. Production releases should use production-only App Attest.` : `Store the generated key on your server; never embed it in a mobile application. Run agw app snippet ${app2.id} for this request again.`
|
|
17078
17126
|
};
|
|
17079
17127
|
}
|
|
17080
17128
|
}
|
|
@@ -17173,9 +17221,11 @@ var REJECTION_REASONS = [
|
|
|
17173
17221
|
"blocked_app_rate",
|
|
17174
17222
|
"blocked_app_budget",
|
|
17175
17223
|
"blocked_billing",
|
|
17176
|
-
"blocked_user"
|
|
17224
|
+
"blocked_user",
|
|
17225
|
+
/** An App Attest assertion whose counter the install had already used. */
|
|
17226
|
+
"blocked_replay"
|
|
17177
17227
|
];
|
|
17178
|
-
var REJECTION_SCOPES = ["user", "app", "account"];
|
|
17228
|
+
var REJECTION_SCOPES = ["user", "install", "app", "account"];
|
|
17179
17229
|
|
|
17180
17230
|
// ../src/contracts/billing.ts
|
|
17181
17231
|
var BillingSubscriptionStatusSchema = external_exports.enum([
|
|
@@ -17326,6 +17376,7 @@ var USAGE_BREAKDOWN_DIMENSIONS = [
|
|
|
17326
17376
|
"credential_source",
|
|
17327
17377
|
"model_author",
|
|
17328
17378
|
"user",
|
|
17379
|
+
"install",
|
|
17329
17380
|
"status",
|
|
17330
17381
|
"cost_source",
|
|
17331
17382
|
"route",
|
|
@@ -17337,7 +17388,7 @@ var ErrorResponseSchema = external_exports.object({
|
|
|
17337
17388
|
code: external_exports.string(),
|
|
17338
17389
|
message: external_exports.string(),
|
|
17339
17390
|
data: external_exports.record(external_exports.string(), external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()])).optional().meta({
|
|
17340
|
-
description: "Machine-readable facts about this rejection, present only where the code alone is not actionable. A billing_request_quota_exceeded rejection carries periodId, periodStart, periodEnd, limit, used, and resetAt; a billing_plan_limit_reached rejection carries limit and used; an app_rate_limited or app_budget_exhausted rejection carries scope,
|
|
17391
|
+
description: "Machine-readable facts about this rejection, present only where the code alone is not actionable. A billing_request_quota_exceeded rejection carries periodId, periodStart, periodEnd, limit, used, and resetAt; a billing_plan_limit_reached rejection carries limit and used; an app_rate_limited or app_budget_exhausted rejection carries scope, one of user, install or app; a rate_limited rejection carries scope naming the endpoint policy that refused, plus limit, windowSeconds, retryAfterSeconds and resetAt."
|
|
17341
17392
|
})
|
|
17342
17393
|
})
|
|
17343
17394
|
}).meta({ id: "ErrorResponse" });
|
|
@@ -17367,17 +17418,23 @@ var AppAttestChallengeResponseSchema = external_exports.object({
|
|
|
17367
17418
|
var AppAttestRegisterResponseSchema = external_exports.object({ user_id: external_exports.string() });
|
|
17368
17419
|
var GatewayTokenResponseSchema = external_exports.object({
|
|
17369
17420
|
access_token: external_exports.string(),
|
|
17370
|
-
expires_in: external_exports.number()
|
|
17421
|
+
expires_in: external_exports.number(),
|
|
17422
|
+
verify_on: external_exports.enum(APP_ATTEST_VERIFY_ON).optional().meta({
|
|
17423
|
+
description: "On App Attest applications, when the gateway verifies the install's assertion: every_request means every request sent with this token must carry X-AppAttest-Proof; token_exchange means requests carry only the token. Absent on other applications."
|
|
17424
|
+
})
|
|
17371
17425
|
});
|
|
17372
17426
|
var CurrentUserResponseSchema = external_exports.object({
|
|
17373
17427
|
user_id: external_exports.string(),
|
|
17428
|
+
install_id: external_exports.string().nullable().meta({
|
|
17429
|
+
description: "The App Attest key id of the install making the request, on App Attest applications, whose request limits are counted per install. Null on server applications."
|
|
17430
|
+
}),
|
|
17374
17431
|
limits: external_exports.object({
|
|
17375
|
-
requests_today: external_exports.number().int().nullable().meta({ description: "Requests
|
|
17432
|
+
requests_today: external_exports.number().int().nullable().meta({ description: "Requests made so far in the current UTC day: by this install on an App Attest application, by this user on a server application. Null when the application sets no per-user limit, in which case requests are not counted at all." }),
|
|
17376
17433
|
requests_remaining: external_exports.number().int().nullable().meta({ description: "What is left of requests_per_day. Null when no daily limit is set." }),
|
|
17377
|
-
requests_per_minute: external_exports.number().nullable().meta({ description: "The per-
|
|
17378
|
-
requests_per_day: external_exports.number().nullable().meta({ description: "The per-
|
|
17379
|
-
monthly_cost_usd: external_exports.number().meta({ description: "What
|
|
17380
|
-
monthly_budget_usd: external_exports.number().nullable().meta({ description: "The
|
|
17434
|
+
requests_per_minute: external_exports.number().nullable().meta({ description: "The per-minute limit this app sets on each install (App Attest) or user (server). Null means unlimited." }),
|
|
17435
|
+
requests_per_day: external_exports.number().nullable().meta({ description: "The per-day limit this app sets on each install (App Attest) or user (server). Null means unlimited." }),
|
|
17436
|
+
monthly_cost_usd: external_exports.number().meta({ description: "What has been spent so far in the current UTC calendar month against the budget below: by this install, or by this user when the budget's scope is user." }),
|
|
17437
|
+
monthly_budget_usd: external_exports.number().nullable().meta({ description: "The monthly spending budget this app sets on each install or user, per limits.per_user.spending.scope. Null means unlimited." }),
|
|
17381
17438
|
blocked: external_exports.boolean().meta({ description: "Whether this user has been blocked in the console." })
|
|
17382
17439
|
}).meta({
|
|
17383
17440
|
description: "The limits the app sets on this user, and where the user stands against them. The account's request allowance is not reported here: it is shared by all apps, and is reported on the rejection that spends it."
|
|
@@ -17387,6 +17444,9 @@ var UsageEventSchema = external_exports.object({
|
|
|
17387
17444
|
id: external_exports.number().int(),
|
|
17388
17445
|
/** Null for an application that identifies no end users. */
|
|
17389
17446
|
user_id: external_exports.string().nullable(),
|
|
17447
|
+
install_id: external_exports.string().nullable().meta({
|
|
17448
|
+
description: "The App Attest key id of the install that made the request, on App Attest applications; null for server applications."
|
|
17449
|
+
}),
|
|
17390
17450
|
api_key_id: external_exports.string().nullable().meta({
|
|
17391
17451
|
description: "Non-secret ID of the application API key that authenticated the request, including the client-proof key carried by an exchanged gateway token."
|
|
17392
17452
|
}),
|
|
@@ -17468,6 +17528,9 @@ var AuthEventListSchema = external_exports.object({
|
|
|
17468
17528
|
var RejectionEventSchema = external_exports.object({
|
|
17469
17529
|
id: external_exports.number().int(),
|
|
17470
17530
|
user_id: external_exports.string().nullable(),
|
|
17531
|
+
install_id: external_exports.string().nullable().meta({
|
|
17532
|
+
description: "The App Attest key id of the refused install, on App Attest applications; null for server applications and for samples recorded before installs were."
|
|
17533
|
+
}),
|
|
17471
17534
|
api_key_id: external_exports.string().nullable(),
|
|
17472
17535
|
reason: external_exports.enum(REJECTION_REASONS),
|
|
17473
17536
|
scope: external_exports.enum(REJECTION_SCOPES).nullable().meta({ description: "Null on historical samples whose limit scope cannot be recovered." }),
|
|
@@ -17526,6 +17589,12 @@ var AuthEventSummarySchema = external_exports.object({
|
|
|
17526
17589
|
description: "Users currently inside an unclosed claim-propagation window \u2014 stuck mid-activation right now."
|
|
17527
17590
|
})
|
|
17528
17591
|
}).meta({ id: "AuthEventSummary" });
|
|
17592
|
+
var AppWarningSchema = external_exports.object({
|
|
17593
|
+
code: external_exports.string().meta({ description: "Stable identifier of what the warning is about." }),
|
|
17594
|
+
message: external_exports.string().meta({ description: "What will stop, when, and what to do about it, in one sentence or two." }),
|
|
17595
|
+
until: external_exports.string().optional().meta({ description: "ISO 8601 UTC instant the behaviour stops." }),
|
|
17596
|
+
docs_url: external_exports.string().optional().meta({ description: "Where the change is described." })
|
|
17597
|
+
}).meta({ id: "AppWarning" });
|
|
17529
17598
|
var AppResponseSchema = external_exports.object({
|
|
17530
17599
|
app: external_exports.object({
|
|
17531
17600
|
revision: external_exports.number().int().positive(),
|
|
@@ -17539,7 +17608,10 @@ var AppResponseSchema = external_exports.object({
|
|
|
17539
17608
|
config: AppConfigSchema,
|
|
17540
17609
|
status: external_exports.enum(APP_STATUSES),
|
|
17541
17610
|
created_at: external_exports.string(),
|
|
17542
|
-
updated_at: external_exports.string()
|
|
17611
|
+
updated_at: external_exports.string(),
|
|
17612
|
+
warnings: external_exports.array(AppWarningSchema).meta({
|
|
17613
|
+
description: "Behaviour of this application that will stop on a stated date, computed when the application is read; empty when there is none. Read-only: tell the person who owns the app, and act before each date."
|
|
17614
|
+
})
|
|
17543
17615
|
})
|
|
17544
17616
|
}).meta({ id: "AppResponse" });
|
|
17545
17617
|
var AppDeleteResponseSchema = external_exports.object({
|
|
@@ -17870,6 +17942,9 @@ var AppCheckResponseSchema = external_exports.object({
|
|
|
17870
17942
|
}),
|
|
17871
17943
|
limitations: external_exports.array(external_exports.string()).meta({
|
|
17872
17944
|
description: "What this check did not exercise, one sentence each."
|
|
17945
|
+
}),
|
|
17946
|
+
warnings: external_exports.array(AppWarningSchema).meta({
|
|
17947
|
+
description: "The application's warnings, as reading it returns them: behaviour that will stop on a stated date. They never make an application not ready."
|
|
17873
17948
|
})
|
|
17874
17949
|
});
|
|
17875
17950
|
var AppSnippetResponseSchema = external_exports.object({
|
|
@@ -17912,9 +17987,16 @@ var ApiKeyRevokeResponseSchema = external_exports.object({
|
|
|
17912
17987
|
var GatewayUserSchema = external_exports.object({
|
|
17913
17988
|
id: external_exports.string(),
|
|
17914
17989
|
status: external_exports.enum(["active", "blocked"]),
|
|
17915
|
-
attest_key_id: external_exports.string().nullable()
|
|
17916
|
-
|
|
17917
|
-
|
|
17990
|
+
attest_key_id: external_exports.string().nullable().meta({
|
|
17991
|
+
description: "The user's most recently seen App Attest key id, if they hold any. Under app_install it is the user's own id."
|
|
17992
|
+
}),
|
|
17993
|
+
attest_registered: external_exports.boolean().meta({ description: "Whether the user holds at least one App Attest key." }),
|
|
17994
|
+
installs: external_exports.number().int().meta({
|
|
17995
|
+
description: "How many App Attest keys the user holds: one per install, that is one copy of the app on one device, and a new one each time the app is reinstalled. Always 0 on server applications."
|
|
17996
|
+
}),
|
|
17997
|
+
is_install: external_exports.boolean().meta({
|
|
17998
|
+
description: "Whether this row's id is itself a registered App Attest key, so the row is one install: every row of an app_install application, and none of a signed-in user's. Decided per row, so history kept from before an application changed its user identity reads as what it was. A per-install budget measures a row's spend only when this is true."
|
|
17999
|
+
}),
|
|
17918
18000
|
created_at: external_exports.string(),
|
|
17919
18001
|
last_seen_at: external_exports.string().nullable(),
|
|
17920
18002
|
is_virtual: external_exports.boolean(),
|
|
@@ -18018,7 +18100,8 @@ var PricesResponseSchema = external_exports.object({
|
|
|
18018
18100
|
var OperationResultSchema = external_exports.object({
|
|
18019
18101
|
/** The account a claim settled, a login landed in, or a bootstrap created. */
|
|
18020
18102
|
accountId: external_exports.string().optional(),
|
|
18021
|
-
|
|
18103
|
+
// An outcome recorded before warnings existed has none.
|
|
18104
|
+
app: AppResponseSchema.shape.app.extend({ warnings: AppResponseSchema.shape.app.shape.warnings.optional() }).optional(),
|
|
18022
18105
|
api_key: AppKeyMetadataSchema.nullable().optional(),
|
|
18023
18106
|
provider: ProviderSummarySchema.optional(),
|
|
18024
18107
|
gateway: ProviderGatewaySummarySchema.optional()
|
|
@@ -18045,7 +18128,7 @@ var RevealedOperationResponseSchema = external_exports.object({
|
|
|
18045
18128
|
id: external_exports.string(),
|
|
18046
18129
|
kind: external_exports.string(),
|
|
18047
18130
|
result: external_exports.object({
|
|
18048
|
-
app: AppResponseSchema.shape.app.optional(),
|
|
18131
|
+
app: AppResponseSchema.shape.app.extend({ warnings: AppResponseSchema.shape.app.shape.warnings.optional() }).optional(),
|
|
18049
18132
|
/** `key` is the plaintext. It is shown this once; the gateway keeps only a hash. */
|
|
18050
18133
|
api_key: CreatedApiKeySchema.nullable().optional()
|
|
18051
18134
|
})
|
|
@@ -18366,6 +18449,9 @@ var GatewayClientHeadersSchema = external_exports.object({
|
|
|
18366
18449
|
"x-app-version": external_exports.string().optional().meta({
|
|
18367
18450
|
description: "Required for gateway-token clients; optional for issuer-less API-key clients."
|
|
18368
18451
|
}),
|
|
18452
|
+
"x-appattest-proof": external_exports.string().regex(/^v1\.[0-9]{1,12}\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]+$/).optional().meta({
|
|
18453
|
+
description: "Required on every request sent with the gateway token of an App Attest application whose authentication.app_attest.verify_on is every_request; ignored, and never forwarded, where verify_on is token_exchange and for API-key clients. Format `v1.<timestamp>.<nonce>.<assertion>`: decimal unix seconds from the device clock (signed, but not compared with the gateway's clock), 16 random bytes as base64url without padding, and the CBOR assertion from DCAppAttestService.generateAssertion as base64url without padding. The assertion's client data is the SHA-256 of these lines joined by \\n with no trailing newline: `appaigateway-request-v1`, the app id, the upper-case HTTP method, the URL path and query exactly as sent, base64url(sha256(body bytes)) (an absent body hashes as empty), base64url(sha256(the bearer token)), the timestamp, and the nonce. Missing answers 401 assertion_required; refused answers 403 attest_failed. The AppAIGateway Swift package 1.4 or later computes it."
|
|
18454
|
+
}),
|
|
18369
18455
|
"x-end-user-id": external_exports.string().optional().meta({
|
|
18370
18456
|
description: "Optional configured end-user identity for issuer-less API-key applications."
|
|
18371
18457
|
})
|
|
@@ -18486,7 +18572,7 @@ var CATALOG = {
|
|
|
18486
18572
|
path: "/v1/apps/{app}/auth/token",
|
|
18487
18573
|
tags: ["Application authentication"],
|
|
18488
18574
|
summary: "Exchange issuer identity and client proof for a gateway token",
|
|
18489
|
-
description: "App Attest clients send key_id, assertion, and challenge. Issuer-backed API-key clients send api_key and issuer_token. The verified issuer claim is always the resulting user identity.",
|
|
18575
|
+
description: "App Attest clients send key_id, assertion, and challenge; the assertion is verified here whatever the application's verify_on, and the answer's verify_on says whether requests sent with the token must also carry X-AppAttest-Proof. Issuer-backed API-key clients send api_key and issuer_token. The verified issuer claim is always the resulting user identity.",
|
|
18490
18576
|
security: "public",
|
|
18491
18577
|
params: APP_PARAM,
|
|
18492
18578
|
request: external_exports.union([AppAttestTokenRequestSchema, ApiKeyTokenRequestSchema]),
|
|
@@ -18499,8 +18585,10 @@ var CATALOG = {
|
|
|
18499
18585
|
path: "/v1/apps/{app}/me",
|
|
18500
18586
|
tags: ["Application"],
|
|
18501
18587
|
summary: "Get the current user's limits, spend and block state",
|
|
18588
|
+
description: "On an App Attest application the request limits and, by default, the budget are the install's; install_id names it. Signed with X-AppAttest-Proof like every other request where the application verifies App Attest on every request.",
|
|
18502
18589
|
security: "gateway",
|
|
18503
18590
|
params: APP_PARAM,
|
|
18591
|
+
headers: GatewayClientHeadersSchema,
|
|
18504
18592
|
response: CurrentUserResponseSchema,
|
|
18505
18593
|
responseDescription: "Current user state.",
|
|
18506
18594
|
errors: { 402: NO_PLAN, 404: NO_END_USERS }
|
|
@@ -18963,6 +19051,7 @@ var CATALOG = {
|
|
|
18963
19051
|
status: external_exports.enum(USAGE_STATUSES).optional(),
|
|
18964
19052
|
provider: external_exports.string().optional(),
|
|
18965
19053
|
user: external_exports.string().optional(),
|
|
19054
|
+
install: external_exports.string().optional().meta({ description: "Only events of this install: an App Attest key id." }),
|
|
18966
19055
|
model: external_exports.string().optional(),
|
|
18967
19056
|
before_id: BeforeIdSchema
|
|
18968
19057
|
}),
|
|
@@ -19141,7 +19230,7 @@ var CATALOG = {
|
|
|
19141
19230
|
security: "management",
|
|
19142
19231
|
params: APP_PARAM,
|
|
19143
19232
|
query: RangeQuerySchema.extend({
|
|
19144
|
-
by: external_exports.enum(USAGE_BREAKDOWN_DIMENSIONS).default("model").meta({ description: "Which dimension to group by. Defaults to model." }),
|
|
19233
|
+
by: external_exports.enum(USAGE_BREAKDOWN_DIMENSIONS).default("model").meta({ description: "Which dimension to group by. Defaults to model. install groups an App Attest application's traffic by the install \u2014 the App Attest key \u2014 that made it; server applications have none." }),
|
|
19145
19234
|
limit: PageLimitSchema
|
|
19146
19235
|
}),
|
|
19147
19236
|
response: BreakdownResponseSchema,
|
|
@@ -21701,7 +21790,12 @@ function list(command, result, style2) {
|
|
|
21701
21790
|
}
|
|
21702
21791
|
function show(command, result, style2) {
|
|
21703
21792
|
if (command === "app show" && "app" in result && !("guidance" in result)) {
|
|
21704
|
-
return [
|
|
21793
|
+
return [
|
|
21794
|
+
style2.headline(`${result.app.name} (${result.app.id})`),
|
|
21795
|
+
...warnings(result.app.warnings ?? [], style2),
|
|
21796
|
+
"",
|
|
21797
|
+
style2.json(result)
|
|
21798
|
+
];
|
|
21705
21799
|
}
|
|
21706
21800
|
if ("slug" in result)
|
|
21707
21801
|
return [
|
|
@@ -21879,7 +21973,8 @@ function app(command, result, context, style2) {
|
|
|
21879
21973
|
],
|
|
21880
21974
|
style2
|
|
21881
21975
|
),
|
|
21882
|
-
...notes(result.limitations)
|
|
21976
|
+
...notes(result.limitations),
|
|
21977
|
+
...warnings(result.warnings ?? [], style2)
|
|
21883
21978
|
];
|
|
21884
21979
|
if ("definition" in result) {
|
|
21885
21980
|
const dryRun = "dryRun" in result;
|
|
@@ -21906,6 +22001,14 @@ function app(command, result, context, style2) {
|
|
|
21906
22001
|
return written(command, result, context, style2);
|
|
21907
22002
|
return [style2.json(result)];
|
|
21908
22003
|
}
|
|
22004
|
+
function warnings(values, style2) {
|
|
22005
|
+
if (!values.length) return [];
|
|
22006
|
+
return [
|
|
22007
|
+
"",
|
|
22008
|
+
style2.warn("Warnings"),
|
|
22009
|
+
...values.map((warning) => `- ${warning.message}${warning.docs_url ? ` See ${warning.docs_url}` : ""}`)
|
|
22010
|
+
];
|
|
22011
|
+
}
|
|
21909
22012
|
var notes = (values) => values.length ? ["", ...values.map((value) => `- ${value}`)] : [];
|
|
21910
22013
|
function written(command, result, context, style2) {
|
|
21911
22014
|
const parsed = AppConfigSchema.safeParse(result.app.config);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maxceem/agw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Manage App AI Gateway from a terminal or coding agent: providers, iOS and server apps, usage, and self-hosted deployment on Cloudflare",
|
|
6
6
|
"keywords": [
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"bugs": "https://github.com/maxceem/app-ai-gateway/issues",
|
|
28
28
|
"upgradeFrom": [
|
|
29
|
+
"0.7.2",
|
|
29
30
|
"0.7.1",
|
|
30
31
|
"0.7.0",
|
|
31
32
|
"0.6.4",
|