primitive 1.2.1 → 1.5.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/oclif/index.js +1554 -57
- package/package.json +7 -1
package/dist/oclif/index.js
CHANGED
|
@@ -3,9 +3,9 @@ import { Args, Command, Errors, Flags, ux } from "@oclif/core";
|
|
|
3
3
|
import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
import path, { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
6
|
-
import { hostname } from "node:os";
|
|
7
6
|
import process$1 from "node:process";
|
|
8
7
|
import { createInterface } from "node:readline/promises";
|
|
8
|
+
import { hostname } from "node:os";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
10
|
//#region \0rolldown/runtime.js
|
|
11
11
|
var __defProp = Object.defineProperty;
|
|
@@ -26,16 +26,20 @@ const client = createClient(createConfig({ baseUrl: "https://api.primitive.dev/v
|
|
|
26
26
|
var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
27
27
|
addDomain: () => addDomain,
|
|
28
28
|
cliLogout: () => cliLogout,
|
|
29
|
+
createAgentAccount: () => createAgentAccount,
|
|
30
|
+
createAgentClaimLink: () => createAgentClaimLink,
|
|
29
31
|
createEndpoint: () => createEndpoint,
|
|
30
32
|
createFilter: () => createFilter,
|
|
31
33
|
createFunction: () => createFunction,
|
|
32
34
|
createFunctionSecret: () => createFunctionSecret,
|
|
35
|
+
createOrgSecret: () => createOrgSecret,
|
|
33
36
|
deleteDomain: () => deleteDomain,
|
|
34
37
|
deleteEmail: () => deleteEmail,
|
|
35
38
|
deleteEndpoint: () => deleteEndpoint,
|
|
36
39
|
deleteFilter: () => deleteFilter,
|
|
37
40
|
deleteFunction: () => deleteFunction,
|
|
38
41
|
deleteFunctionSecret: () => deleteFunctionSecret,
|
|
42
|
+
deleteOrgSecret: () => deleteOrgSecret,
|
|
39
43
|
discardEmailContent: () => discardEmailContent,
|
|
40
44
|
downloadAttachments: () => downloadAttachments,
|
|
41
45
|
downloadDomainZoneFile: () => downloadDomainZoneFile,
|
|
@@ -61,6 +65,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
|
61
65
|
listFunctionLogs: () => listFunctionLogs,
|
|
62
66
|
listFunctionSecrets: () => listFunctionSecrets,
|
|
63
67
|
listFunctions: () => listFunctions,
|
|
68
|
+
listOrgSecrets: () => listOrgSecrets,
|
|
64
69
|
listSentEmails: () => listSentEmails,
|
|
65
70
|
pollCliLogin: () => pollCliLogin,
|
|
66
71
|
replayDelivery: () => replayDelivery,
|
|
@@ -74,6 +79,8 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
|
74
79
|
sendEmail: () => sendEmail,
|
|
75
80
|
setFunctionRoute: () => setFunctionRoute,
|
|
76
81
|
setFunctionSecret: () => setFunctionSecret,
|
|
82
|
+
setOrgSecret: () => setOrgSecret,
|
|
83
|
+
startAgentClaim: () => startAgentClaim,
|
|
77
84
|
startAgentSignup: () => startAgentSignup,
|
|
78
85
|
startCliLogin: () => startCliLogin,
|
|
79
86
|
startCliSignup: () => startCliSignup,
|
|
@@ -85,6 +92,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
|
85
92
|
updateEndpoint: () => updateEndpoint,
|
|
86
93
|
updateFilter: () => updateFilter,
|
|
87
94
|
updateFunction: () => updateFunction,
|
|
95
|
+
verifyAgentClaim: () => verifyAgentClaim,
|
|
88
96
|
verifyAgentSignup: () => verifyAgentSignup,
|
|
89
97
|
verifyCliSignup: () => verifyCliSignup,
|
|
90
98
|
verifyDomain: () => verifyDomain
|
|
@@ -229,6 +237,92 @@ const verifyAgentSignup = (options) => (options.client ?? client).post({
|
|
|
229
237
|
}
|
|
230
238
|
});
|
|
231
239
|
/**
|
|
240
|
+
* Create an emailless agent account
|
|
241
|
+
*
|
|
242
|
+
* Creates an emailless agent account without authentication and returns a
|
|
243
|
+
* one-time API key (prefixed `prim_`) plus a provisioned managed inbox.
|
|
244
|
+
* The account is on the `agent` plan: reply-only (it can send only to
|
|
245
|
+
* addresses that have already sent it authenticated mail) with tight send
|
|
246
|
+
* limits. Use the returned `api_key` as a Bearer token on later calls. The
|
|
247
|
+
* account can be upgraded to a full developer account by confirming an
|
|
248
|
+
* email through the claim flow. This endpoint does not require an API key.
|
|
249
|
+
*
|
|
250
|
+
*/
|
|
251
|
+
const createAgentAccount = (options) => (options.client ?? client).post({
|
|
252
|
+
url: "/agent/accounts",
|
|
253
|
+
...options,
|
|
254
|
+
headers: {
|
|
255
|
+
...options.body !== void 0 && { "Content-Type": "application/json" },
|
|
256
|
+
...options.headers
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
/**
|
|
260
|
+
* Start an agent account email claim
|
|
261
|
+
*
|
|
262
|
+
* Begins upgrading an emailless `agent` account into a full `developer`
|
|
263
|
+
* account by confirming an email address. Authenticated by the agent's own
|
|
264
|
+
* API key (the org is taken from the credential). Sends a verification
|
|
265
|
+
* code to the supplied email and returns the claim session id plus resend
|
|
266
|
+
* timing. Submit the code to `/agent/claim/verify` to complete the
|
|
267
|
+
* upgrade. Confirming an email that already belongs to a Primitive account
|
|
268
|
+
* is rejected.
|
|
269
|
+
*
|
|
270
|
+
*/
|
|
271
|
+
const startAgentClaim = (options) => (options.client ?? client).post({
|
|
272
|
+
security: [{
|
|
273
|
+
scheme: "bearer",
|
|
274
|
+
type: "http"
|
|
275
|
+
}],
|
|
276
|
+
url: "/agent/claim/start",
|
|
277
|
+
...options,
|
|
278
|
+
headers: {
|
|
279
|
+
...options.body !== void 0 && { "Content-Type": "application/json" },
|
|
280
|
+
...options.headers
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
/**
|
|
284
|
+
* Verify an agent account email claim
|
|
285
|
+
*
|
|
286
|
+
* Confirms the verification code emailed by `/agent/claim/start` and
|
|
287
|
+
* upgrades the account to the `developer` plan. The org id, API key, and
|
|
288
|
+
* managed inbox all carry over; the send cap lifts. Authenticated by the
|
|
289
|
+
* agent's own API key.
|
|
290
|
+
*
|
|
291
|
+
*/
|
|
292
|
+
const verifyAgentClaim = (options) => (options.client ?? client).post({
|
|
293
|
+
security: [{
|
|
294
|
+
scheme: "bearer",
|
|
295
|
+
type: "http"
|
|
296
|
+
}],
|
|
297
|
+
url: "/agent/claim/verify",
|
|
298
|
+
...options,
|
|
299
|
+
headers: {
|
|
300
|
+
...options.body !== void 0 && { "Content-Type": "application/json" },
|
|
301
|
+
...options.headers
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
/**
|
|
305
|
+
* Create a browser claim link
|
|
306
|
+
*
|
|
307
|
+
* Mints an opaque, single-use link an agent can hand to a human to
|
|
308
|
+
* complete the email-confirmation upgrade in a browser. Authenticated by
|
|
309
|
+
* the agent's own API key. `claim_url` is null when the API host cannot
|
|
310
|
+
* resolve a web origin to build the link.
|
|
311
|
+
*
|
|
312
|
+
*/
|
|
313
|
+
const createAgentClaimLink = (options) => (options?.client ?? client).post({
|
|
314
|
+
security: [{
|
|
315
|
+
scheme: "bearer",
|
|
316
|
+
type: "http"
|
|
317
|
+
}],
|
|
318
|
+
url: "/agent/claim/link",
|
|
319
|
+
...options,
|
|
320
|
+
headers: {
|
|
321
|
+
"Content-Type": "application/json",
|
|
322
|
+
...options?.headers
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
/**
|
|
232
326
|
* Revoke the current CLI OAuth session
|
|
233
327
|
*
|
|
234
328
|
* Revokes the OAuth grant used to authenticate the request. API-key
|
|
@@ -1104,10 +1198,12 @@ const listFunctions = (options) => (options?.client ?? client).get({
|
|
|
1104
1198
|
* each delivery and forwards the `Primitive-Signature` header to
|
|
1105
1199
|
* the handler. Verify the raw request body with
|
|
1106
1200
|
* `PRIMITIVE_WEBHOOK_SECRET` before parsing JSON; after verification
|
|
1107
|
-
* the request body parses to
|
|
1108
|
-
* `
|
|
1109
|
-
*
|
|
1110
|
-
*
|
|
1201
|
+
* the request body parses to a webhook event whose `event` field is
|
|
1202
|
+
* `email.received` for normal inbound mail, or a machine-mail type
|
|
1203
|
+
* (`email.bounced`, `email.tls_report`, `email.dmarc_report`,
|
|
1204
|
+
* `email.dmarc_failure`) for bounces and reports. Code is bundled
|
|
1205
|
+
* before being uploaded; ship a single self-contained file rather
|
|
1206
|
+
* than relying on external imports.
|
|
1111
1207
|
*
|
|
1112
1208
|
* **Code limits.** `code` is capped at 1 MiB UTF-8. `sourceMap`
|
|
1113
1209
|
* (optional) is capped at 5 MiB UTF-8, stored with each deployment
|
|
@@ -1425,6 +1521,85 @@ const setFunctionSecret = (options) => (options.client ?? client).put({
|
|
|
1425
1521
|
}
|
|
1426
1522
|
});
|
|
1427
1523
|
/**
|
|
1524
|
+
* List org-level (global) secrets
|
|
1525
|
+
*
|
|
1526
|
+
* Returns metadata for every org-level secret. Org secrets apply
|
|
1527
|
+
* to every function in the org and are read as `env.<KEY>` in
|
|
1528
|
+
* handlers. **Values are never returned.** Secret writes are
|
|
1529
|
+
* write-only. A function-level secret of the same name overrides
|
|
1530
|
+
* the org-level value for that function.
|
|
1531
|
+
*
|
|
1532
|
+
*/
|
|
1533
|
+
const listOrgSecrets = (options) => (options?.client ?? client).get({
|
|
1534
|
+
security: [{
|
|
1535
|
+
scheme: "bearer",
|
|
1536
|
+
type: "http"
|
|
1537
|
+
}],
|
|
1538
|
+
url: "/org/secrets",
|
|
1539
|
+
...options
|
|
1540
|
+
});
|
|
1541
|
+
/**
|
|
1542
|
+
* Create or update an org secret
|
|
1543
|
+
*
|
|
1544
|
+
* Idempotent insert-or-update keyed on `(org_id, key)`. Returns
|
|
1545
|
+
* 201 the first time the key is set, 200 on subsequent updates.
|
|
1546
|
+
* Values are encrypted at rest. A changed value lands in a
|
|
1547
|
+
* function only on that function's next deploy.
|
|
1548
|
+
*
|
|
1549
|
+
* Keys must match `^[A-Z_][A-Z0-9_]*$` (uppercase letters,
|
|
1550
|
+
* digits, underscores; first character is a letter or
|
|
1551
|
+
* underscore). Values are at most 4096 UTF-8 bytes. System-
|
|
1552
|
+
* managed keys are reserved and rejected.
|
|
1553
|
+
*
|
|
1554
|
+
*/
|
|
1555
|
+
const createOrgSecret = (options) => (options.client ?? client).post({
|
|
1556
|
+
security: [{
|
|
1557
|
+
scheme: "bearer",
|
|
1558
|
+
type: "http"
|
|
1559
|
+
}],
|
|
1560
|
+
url: "/org/secrets",
|
|
1561
|
+
...options,
|
|
1562
|
+
headers: {
|
|
1563
|
+
...options.body !== void 0 && { "Content-Type": "application/json" },
|
|
1564
|
+
...options.headers
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
/**
|
|
1568
|
+
* Delete an org secret
|
|
1569
|
+
*
|
|
1570
|
+
* Removes the org secret. Functions keep the previous value until
|
|
1571
|
+
* each is redeployed. Returns 404 if the key did not exist.
|
|
1572
|
+
*
|
|
1573
|
+
*/
|
|
1574
|
+
const deleteOrgSecret = (options) => (options.client ?? client).delete({
|
|
1575
|
+
security: [{
|
|
1576
|
+
scheme: "bearer",
|
|
1577
|
+
type: "http"
|
|
1578
|
+
}],
|
|
1579
|
+
url: "/org/secrets/{key}",
|
|
1580
|
+
...options
|
|
1581
|
+
});
|
|
1582
|
+
/**
|
|
1583
|
+
* Set an org secret by key
|
|
1584
|
+
*
|
|
1585
|
+
* Path-keyed companion to `POST /org/secrets`. Idempotent:
|
|
1586
|
+
* returns 201 the first time the key is set, 200 on subsequent
|
|
1587
|
+
* updates. Same validation and write-only guarantees as POST.
|
|
1588
|
+
*
|
|
1589
|
+
*/
|
|
1590
|
+
const setOrgSecret = (options) => (options.client ?? client).put({
|
|
1591
|
+
security: [{
|
|
1592
|
+
scheme: "bearer",
|
|
1593
|
+
type: "http"
|
|
1594
|
+
}],
|
|
1595
|
+
url: "/org/secrets/{key}",
|
|
1596
|
+
...options,
|
|
1597
|
+
headers: {
|
|
1598
|
+
...options.body !== void 0 && { "Content-Type": "application/json" },
|
|
1599
|
+
...options.headers
|
|
1600
|
+
}
|
|
1601
|
+
});
|
|
1602
|
+
/**
|
|
1428
1603
|
* List a function's execution logs
|
|
1429
1604
|
*
|
|
1430
1605
|
* Returns the most recent `function_logs` rows for the function,
|
|
@@ -1528,7 +1703,7 @@ const openapiDocument = {
|
|
|
1528
1703
|
},
|
|
1529
1704
|
{
|
|
1530
1705
|
"name": "Functions",
|
|
1531
|
-
"description": "Deploy JavaScript handlers that run on inbound mail. Each function\nis a single ESM module whose default export is an object with an\nasync `fetch(request, env)` method, in the shape of a Workers-style\nhandler. Primitive signs each delivery and forwards the\n`Primitive-Signature` header to the handler; verify the raw request\nbody with `PRIMITIVE_WEBHOOK_SECRET` before trusting the parsed
|
|
1706
|
+
"description": "Deploy JavaScript handlers that run on inbound mail. Each function\nis a single ESM module whose default export is an object with an\nasync `fetch(request, env)` method, in the shape of a Workers-style\nhandler. Primitive signs each delivery and forwards the\n`Primitive-Signature` header to the handler; verify the raw request\nbody with `PRIMITIVE_WEBHOOK_SECRET` before trusting the parsed event.\nThe `event` field is `email.received` for normal inbound mail, or a\nmachine-mail type (`email.bounced`, `email.tls_report`,\n`email.dmarc_report`, `email.dmarc_failure`) for bounces and reports;\nthe payload shape is otherwise identical. Code runs on\nPrimitive's edge runtime; there is no infrastructure to manage.\nSecrets land in `env` as encrypted bindings and are refreshed on\nevery redeploy.\n"
|
|
1532
1707
|
}
|
|
1533
1708
|
],
|
|
1534
1709
|
"paths": {
|
|
@@ -1834,6 +2009,128 @@ const openapiDocument = {
|
|
|
1834
2009
|
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
1835
2010
|
}
|
|
1836
2011
|
} },
|
|
2012
|
+
"/agent/accounts": { "post": {
|
|
2013
|
+
"operationId": "createAgentAccount",
|
|
2014
|
+
"summary": "Create an emailless agent account",
|
|
2015
|
+
"description": "Creates an emailless agent account without authentication and returns a\none-time API key (prefixed `prim_`) plus a provisioned managed inbox.\nThe account is on the `agent` plan: reply-only (it can send only to\naddresses that have already sent it authenticated mail) with tight send\nlimits. Use the returned `api_key` as a Bearer token on later calls. The\naccount can be upgraded to a full developer account by confirming an\nemail through the claim flow. This endpoint does not require an API key.\n",
|
|
2016
|
+
"tags": ["Agent"],
|
|
2017
|
+
"security": [],
|
|
2018
|
+
"requestBody": {
|
|
2019
|
+
"required": true,
|
|
2020
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateAgentAccountInput" } } }
|
|
2021
|
+
},
|
|
2022
|
+
"responses": {
|
|
2023
|
+
"200": {
|
|
2024
|
+
"description": "Agent account created; the API key is returned once",
|
|
2025
|
+
"headers": { "Cache-Control": {
|
|
2026
|
+
"schema": { "type": "string" },
|
|
2027
|
+
"description": "Always `no-store`"
|
|
2028
|
+
} },
|
|
2029
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
2030
|
+
"type": "object",
|
|
2031
|
+
"properties": { "data": { "$ref": "#/components/schemas/AgentAccountResult" } }
|
|
2032
|
+
}] } } }
|
|
2033
|
+
},
|
|
2034
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
2035
|
+
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
2036
|
+
}
|
|
2037
|
+
} },
|
|
2038
|
+
"/agent/claim/start": { "post": {
|
|
2039
|
+
"operationId": "startAgentClaim",
|
|
2040
|
+
"summary": "Start an agent account email claim",
|
|
2041
|
+
"description": "Begins upgrading an emailless `agent` account into a full `developer`\naccount by confirming an email address. Authenticated by the agent's own\nAPI key (the org is taken from the credential). Sends a verification\ncode to the supplied email and returns the claim session id plus resend\ntiming. Submit the code to `/agent/claim/verify` to complete the\nupgrade. Confirming an email that already belongs to a Primitive account\nis rejected.\n",
|
|
2042
|
+
"tags": ["Agent"],
|
|
2043
|
+
"requestBody": {
|
|
2044
|
+
"required": true,
|
|
2045
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/StartAgentClaimInput" } } }
|
|
2046
|
+
},
|
|
2047
|
+
"responses": {
|
|
2048
|
+
"200": {
|
|
2049
|
+
"description": "Claim started and verification email sent",
|
|
2050
|
+
"headers": { "Cache-Control": {
|
|
2051
|
+
"schema": { "type": "string" },
|
|
2052
|
+
"description": "Always `no-store`"
|
|
2053
|
+
} },
|
|
2054
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
2055
|
+
"type": "object",
|
|
2056
|
+
"properties": { "data": { "$ref": "#/components/schemas/AgentClaimStartResult" } }
|
|
2057
|
+
}] } } }
|
|
2058
|
+
},
|
|
2059
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
2060
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
2061
|
+
"404": { "$ref": "#/components/responses/NotFound" },
|
|
2062
|
+
"409": {
|
|
2063
|
+
"description": "The email is already in use, or the account is not claimable",
|
|
2064
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
|
|
2065
|
+
},
|
|
2066
|
+
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
2067
|
+
}
|
|
2068
|
+
} },
|
|
2069
|
+
"/agent/claim/verify": { "post": {
|
|
2070
|
+
"operationId": "verifyAgentClaim",
|
|
2071
|
+
"summary": "Verify an agent account email claim",
|
|
2072
|
+
"description": "Confirms the verification code emailed by `/agent/claim/start` and\nupgrades the account to the `developer` plan. The org id, API key, and\nmanaged inbox all carry over; the send cap lifts. Authenticated by the\nagent's own API key.\n",
|
|
2073
|
+
"tags": ["Agent"],
|
|
2074
|
+
"requestBody": {
|
|
2075
|
+
"required": true,
|
|
2076
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/VerifyAgentClaimInput" } } }
|
|
2077
|
+
},
|
|
2078
|
+
"responses": {
|
|
2079
|
+
"200": {
|
|
2080
|
+
"description": "Claim verified; account upgraded to developer",
|
|
2081
|
+
"headers": { "Cache-Control": {
|
|
2082
|
+
"schema": { "type": "string" },
|
|
2083
|
+
"description": "Always `no-store`"
|
|
2084
|
+
} },
|
|
2085
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
2086
|
+
"type": "object",
|
|
2087
|
+
"properties": { "data": { "$ref": "#/components/schemas/AgentClaimResult" } }
|
|
2088
|
+
}] } } }
|
|
2089
|
+
},
|
|
2090
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
2091
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
2092
|
+
"404": { "$ref": "#/components/responses/NotFound" },
|
|
2093
|
+
"409": {
|
|
2094
|
+
"description": "The account is already claimed, or the email is in use",
|
|
2095
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
|
|
2096
|
+
},
|
|
2097
|
+
"410": {
|
|
2098
|
+
"description": "The claim or its verification code has expired",
|
|
2099
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
|
|
2100
|
+
},
|
|
2101
|
+
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
2102
|
+
}
|
|
2103
|
+
} },
|
|
2104
|
+
"/agent/claim/link": { "post": {
|
|
2105
|
+
"operationId": "createAgentClaimLink",
|
|
2106
|
+
"summary": "Create a browser claim link",
|
|
2107
|
+
"description": "Mints an opaque, single-use link an agent can hand to a human to\ncomplete the email-confirmation upgrade in a browser. Authenticated by\nthe agent's own API key. `claim_url` is null when the API host cannot\nresolve a web origin to build the link.\n",
|
|
2108
|
+
"tags": ["Agent"],
|
|
2109
|
+
"requestBody": {
|
|
2110
|
+
"required": false,
|
|
2111
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateAgentClaimLinkInput" } } }
|
|
2112
|
+
},
|
|
2113
|
+
"responses": {
|
|
2114
|
+
"200": {
|
|
2115
|
+
"description": "Claim link created",
|
|
2116
|
+
"headers": { "Cache-Control": {
|
|
2117
|
+
"schema": { "type": "string" },
|
|
2118
|
+
"description": "Always `no-store`"
|
|
2119
|
+
} },
|
|
2120
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
2121
|
+
"type": "object",
|
|
2122
|
+
"properties": { "data": { "$ref": "#/components/schemas/AgentClaimLinkResult" } }
|
|
2123
|
+
}] } } }
|
|
2124
|
+
},
|
|
2125
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
2126
|
+
"404": { "$ref": "#/components/responses/NotFound" },
|
|
2127
|
+
"409": {
|
|
2128
|
+
"description": "The account is not claimable (not an agent account, or already claimed)",
|
|
2129
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
|
|
2130
|
+
},
|
|
2131
|
+
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
2132
|
+
}
|
|
2133
|
+
} },
|
|
1837
2134
|
"/cli/logout": { "post": {
|
|
1838
2135
|
"operationId": "cliLogout",
|
|
1839
2136
|
"summary": "Revoke the current CLI OAuth session",
|
|
@@ -2178,6 +2475,25 @@ const openapiDocument = {
|
|
|
2178
2475
|
"format": "date-time"
|
|
2179
2476
|
},
|
|
2180
2477
|
"description": "Filter emails created on or before this timestamp"
|
|
2478
|
+
},
|
|
2479
|
+
{
|
|
2480
|
+
"name": "since",
|
|
2481
|
+
"in": "query",
|
|
2482
|
+
"schema": {
|
|
2483
|
+
"type": "string",
|
|
2484
|
+
"maxLength": 200
|
|
2485
|
+
},
|
|
2486
|
+
"description": "Forward-tail cursor. Returns rows that became visible AFTER this\ncursor, oldest-first, so a caller can stream new inbound mail by\nre-passing the cursor from each response. Mutually exclusive with\n`cursor` (which pages history newest-first). Pass the `meta.cursor`\nfrom the previous `since` response; an empty page means caught up.\n"
|
|
2487
|
+
},
|
|
2488
|
+
{
|
|
2489
|
+
"name": "wait",
|
|
2490
|
+
"in": "query",
|
|
2491
|
+
"schema": {
|
|
2492
|
+
"type": "integer",
|
|
2493
|
+
"minimum": 0,
|
|
2494
|
+
"maximum": 30
|
|
2495
|
+
},
|
|
2496
|
+
"description": "Long-poll: hold the request up to this many seconds waiting for new\nmail past `since`, returning as soon as any arrives (or an empty\npage when the wait elapses). Requires `since`. Omitted means no wait\n(returns immediately); the server treats an absent value as 0. NOT\ngiven an OpenAPI `default` on purpose: a default makes some\ngenerators (e.g. openapi-python-client) send `wait=0` on every call,\nwhich then fails the `wait` requires `since` check for plain history\nlistings.\n"
|
|
2181
2497
|
}
|
|
2182
2498
|
],
|
|
2183
2499
|
"responses": {
|
|
@@ -3117,7 +3433,7 @@ const openapiDocument = {
|
|
|
3117
3433
|
"post": {
|
|
3118
3434
|
"operationId": "createFunction",
|
|
3119
3435
|
"summary": "Deploy a function",
|
|
3120
|
-
"description": "Creates and deploys a new function. The handler must be a single\nESM module whose default export is an object with an async\n`fetch(request, env)` method (Workers-style). Primitive signs\neach delivery and forwards the `Primitive-Signature` header to\nthe handler. Verify the raw request body with\n`PRIMITIVE_WEBHOOK_SECRET` before parsing JSON; after verification\nthe request body parses to
|
|
3436
|
+
"description": "Creates and deploys a new function. The handler must be a single\nESM module whose default export is an object with an async\n`fetch(request, env)` method (Workers-style). Primitive signs\neach delivery and forwards the `Primitive-Signature` header to\nthe handler. Verify the raw request body with\n`PRIMITIVE_WEBHOOK_SECRET` before parsing JSON; after verification\nthe request body parses to a webhook event whose `event` field is\n`email.received` for normal inbound mail, or a machine-mail type\n(`email.bounced`, `email.tls_report`, `email.dmarc_report`,\n`email.dmarc_failure`) for bounces and reports. Code is bundled\nbefore being uploaded; ship a single self-contained file rather\nthan relying on external imports.\n\n**Code limits.** `code` is capped at 1 MiB UTF-8. `sourceMap`\n(optional) is capped at 5 MiB UTF-8, stored with each deployment\nattempt, and sent to the runtime so stack traces can resolve to\noriginal source files.\n\n**Routing.** On successful deploy, the function code is live\nin the runtime, but inbound mail will not reach it until at\nleast one route is bound. Routes are managed from the Primitive\ndashboard. A `deploy_status` of `deployed` means the script is\ninstalled, not that the function is receiving mail. The\ninternal runtime URL is not returned by the API and is not a\ncustomer-facing integration surface.\n\n**Secrets.** New functions ship with the managed secrets\n(`PRIMITIVE_WEBHOOK_SECRET`, `PRIMITIVE_API_KEY`,\n`PRIMITIVE_API_BASE_URL`) already bound. Add user-set secrets via\n`POST /functions/{id}/secrets`; secret writes only land in the\nrunning handler on the next redeploy.\n",
|
|
3121
3437
|
"tags": ["Functions"],
|
|
3122
3438
|
"requestBody": {
|
|
3123
3439
|
"required": true,
|
|
@@ -3394,37 +3710,143 @@ const openapiDocument = {
|
|
|
3394
3710
|
}
|
|
3395
3711
|
},
|
|
3396
3712
|
"post": {
|
|
3397
|
-
"operationId": "createFunctionSecret",
|
|
3398
|
-
"summary": "Create or update a secret",
|
|
3399
|
-
"description": "Idempotent insert-or-update keyed on `(function_id, key)`.\nReturns 201 the first time the key is set, 200 on subsequent\nupdates. Values are encrypted at rest and only become visible\nto the running handler on the next deploy (`PUT /functions/{id}`\nwith the existing code is sufficient to refresh bindings).\n\nKeys must match `^[A-Z_][A-Z0-9_]*$` (uppercase letters,\ndigits, underscores; first character is a letter or\nunderscore). Values are at most 4096 UTF-8 bytes. System-\nmanaged keys are reserved and rejected.\n",
|
|
3713
|
+
"operationId": "createFunctionSecret",
|
|
3714
|
+
"summary": "Create or update a secret",
|
|
3715
|
+
"description": "Idempotent insert-or-update keyed on `(function_id, key)`.\nReturns 201 the first time the key is set, 200 on subsequent\nupdates. Values are encrypted at rest and only become visible\nto the running handler on the next deploy (`PUT /functions/{id}`\nwith the existing code is sufficient to refresh bindings).\n\nKeys must match `^[A-Z_][A-Z0-9_]*$` (uppercase letters,\ndigits, underscores; first character is a letter or\nunderscore). Values are at most 4096 UTF-8 bytes. System-\nmanaged keys are reserved and rejected.\n",
|
|
3716
|
+
"tags": ["Functions"],
|
|
3717
|
+
"requestBody": {
|
|
3718
|
+
"required": true,
|
|
3719
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateFunctionSecretInput" } } }
|
|
3720
|
+
},
|
|
3721
|
+
"responses": {
|
|
3722
|
+
"200": {
|
|
3723
|
+
"description": "Secret updated",
|
|
3724
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
3725
|
+
"type": "object",
|
|
3726
|
+
"properties": { "data": { "$ref": "#/components/schemas/FunctionSecretWriteResult" } }
|
|
3727
|
+
}] } } }
|
|
3728
|
+
},
|
|
3729
|
+
"201": {
|
|
3730
|
+
"description": "Secret created",
|
|
3731
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
3732
|
+
"type": "object",
|
|
3733
|
+
"properties": { "data": { "$ref": "#/components/schemas/FunctionSecretWriteResult" } }
|
|
3734
|
+
}] } } }
|
|
3735
|
+
},
|
|
3736
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
3737
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
3738
|
+
"404": { "$ref": "#/components/responses/NotFound" }
|
|
3739
|
+
}
|
|
3740
|
+
}
|
|
3741
|
+
},
|
|
3742
|
+
"/functions/{id}/secrets/{key}": {
|
|
3743
|
+
"parameters": [{ "$ref": "#/components/parameters/ResourceId" }, {
|
|
3744
|
+
"name": "key",
|
|
3745
|
+
"in": "path",
|
|
3746
|
+
"required": true,
|
|
3747
|
+
"description": "Secret key. Must match `^[A-Z_][A-Z0-9_]*$`.",
|
|
3748
|
+
"schema": {
|
|
3749
|
+
"type": "string",
|
|
3750
|
+
"pattern": "^[A-Z_][A-Z0-9_]*$"
|
|
3751
|
+
}
|
|
3752
|
+
}],
|
|
3753
|
+
"put": {
|
|
3754
|
+
"operationId": "setFunctionSecret",
|
|
3755
|
+
"summary": "Set a secret by key",
|
|
3756
|
+
"description": "Path-keyed companion to `POST /functions/{id}/secrets`.\nIdempotent: returns 201 the first time the key is set, 200 on\nsubsequent updates. Same validation rules and same write-only\nguarantees as the POST verb; the new value lands in the running\nhandler on the next deploy.\n",
|
|
3757
|
+
"tags": ["Functions"],
|
|
3758
|
+
"requestBody": {
|
|
3759
|
+
"required": true,
|
|
3760
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetFunctionSecretInput" } } }
|
|
3761
|
+
},
|
|
3762
|
+
"responses": {
|
|
3763
|
+
"200": {
|
|
3764
|
+
"description": "Secret updated",
|
|
3765
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
3766
|
+
"type": "object",
|
|
3767
|
+
"properties": { "data": { "$ref": "#/components/schemas/FunctionSecretWriteResult" } }
|
|
3768
|
+
}] } } }
|
|
3769
|
+
},
|
|
3770
|
+
"201": {
|
|
3771
|
+
"description": "Secret created",
|
|
3772
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
3773
|
+
"type": "object",
|
|
3774
|
+
"properties": { "data": { "$ref": "#/components/schemas/FunctionSecretWriteResult" } }
|
|
3775
|
+
}] } } }
|
|
3776
|
+
},
|
|
3777
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
3778
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
3779
|
+
"404": { "$ref": "#/components/responses/NotFound" }
|
|
3780
|
+
}
|
|
3781
|
+
},
|
|
3782
|
+
"delete": {
|
|
3783
|
+
"operationId": "deleteFunctionSecret",
|
|
3784
|
+
"summary": "Delete a secret",
|
|
3785
|
+
"description": "Removes the secret. The binding stays live in the running\nhandler until the next deploy refreshes the binding set\n(`PUT /functions/{id}` with the existing code is sufficient).\nReturns 404 if the key did not exist. Managed system keys\ncannot be deleted.\n",
|
|
3786
|
+
"tags": ["Functions"],
|
|
3787
|
+
"responses": {
|
|
3788
|
+
"204": { "description": "Secret deleted" },
|
|
3789
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
3790
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
3791
|
+
"404": { "$ref": "#/components/responses/NotFound" }
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
},
|
|
3795
|
+
"/org/secrets": {
|
|
3796
|
+
"get": {
|
|
3797
|
+
"operationId": "listOrgSecrets",
|
|
3798
|
+
"summary": "List org-level (global) secrets",
|
|
3799
|
+
"description": "Returns metadata for every org-level secret. Org secrets apply\nto every function in the org and are read as `env.<KEY>` in\nhandlers. **Values are never returned.** Secret writes are\nwrite-only. A function-level secret of the same name overrides\nthe org-level value for that function.\n",
|
|
3800
|
+
"tags": ["Functions"],
|
|
3801
|
+
"responses": {
|
|
3802
|
+
"200": {
|
|
3803
|
+
"description": "List of org secrets (metadata only, no values)",
|
|
3804
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
3805
|
+
"type": "object",
|
|
3806
|
+
"properties": { "data": {
|
|
3807
|
+
"type": "object",
|
|
3808
|
+
"properties": { "items": {
|
|
3809
|
+
"type": "array",
|
|
3810
|
+
"items": { "$ref": "#/components/schemas/OrgSecretListItem" }
|
|
3811
|
+
} },
|
|
3812
|
+
"required": ["items"]
|
|
3813
|
+
} }
|
|
3814
|
+
}] } } }
|
|
3815
|
+
},
|
|
3816
|
+
"401": { "$ref": "#/components/responses/Unauthorized" }
|
|
3817
|
+
}
|
|
3818
|
+
},
|
|
3819
|
+
"post": {
|
|
3820
|
+
"operationId": "createOrgSecret",
|
|
3821
|
+
"summary": "Create or update an org secret",
|
|
3822
|
+
"description": "Idempotent insert-or-update keyed on `(org_id, key)`. Returns\n201 the first time the key is set, 200 on subsequent updates.\nValues are encrypted at rest. A changed value lands in a\nfunction only on that function's next deploy.\n\nKeys must match `^[A-Z_][A-Z0-9_]*$` (uppercase letters,\ndigits, underscores; first character is a letter or\nunderscore). Values are at most 4096 UTF-8 bytes. System-\nmanaged keys are reserved and rejected.\n",
|
|
3400
3823
|
"tags": ["Functions"],
|
|
3401
3824
|
"requestBody": {
|
|
3402
3825
|
"required": true,
|
|
3403
|
-
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/
|
|
3826
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateOrgSecretInput" } } }
|
|
3404
3827
|
},
|
|
3405
3828
|
"responses": {
|
|
3406
3829
|
"200": {
|
|
3407
3830
|
"description": "Secret updated",
|
|
3408
3831
|
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
3409
3832
|
"type": "object",
|
|
3410
|
-
"properties": { "data": { "$ref": "#/components/schemas/
|
|
3833
|
+
"properties": { "data": { "$ref": "#/components/schemas/OrgSecretWriteResult" } }
|
|
3411
3834
|
}] } } }
|
|
3412
3835
|
},
|
|
3413
3836
|
"201": {
|
|
3414
3837
|
"description": "Secret created",
|
|
3415
3838
|
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
3416
3839
|
"type": "object",
|
|
3417
|
-
"properties": { "data": { "$ref": "#/components/schemas/
|
|
3840
|
+
"properties": { "data": { "$ref": "#/components/schemas/OrgSecretWriteResult" } }
|
|
3418
3841
|
}] } } }
|
|
3419
3842
|
},
|
|
3420
3843
|
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
3421
|
-
"401": { "$ref": "#/components/responses/Unauthorized" }
|
|
3422
|
-
"404": { "$ref": "#/components/responses/NotFound" }
|
|
3844
|
+
"401": { "$ref": "#/components/responses/Unauthorized" }
|
|
3423
3845
|
}
|
|
3424
3846
|
}
|
|
3425
3847
|
},
|
|
3426
|
-
"/
|
|
3427
|
-
"parameters": [{
|
|
3848
|
+
"/org/secrets/{key}": {
|
|
3849
|
+
"parameters": [{
|
|
3428
3850
|
"name": "key",
|
|
3429
3851
|
"in": "path",
|
|
3430
3852
|
"required": true,
|
|
@@ -3435,38 +3857,37 @@ const openapiDocument = {
|
|
|
3435
3857
|
}
|
|
3436
3858
|
}],
|
|
3437
3859
|
"put": {
|
|
3438
|
-
"operationId": "
|
|
3439
|
-
"summary": "Set
|
|
3440
|
-
"description": "Path-keyed companion to `POST /
|
|
3860
|
+
"operationId": "setOrgSecret",
|
|
3861
|
+
"summary": "Set an org secret by key",
|
|
3862
|
+
"description": "Path-keyed companion to `POST /org/secrets`. Idempotent:\nreturns 201 the first time the key is set, 200 on subsequent\nupdates. Same validation and write-only guarantees as POST.\n",
|
|
3441
3863
|
"tags": ["Functions"],
|
|
3442
3864
|
"requestBody": {
|
|
3443
3865
|
"required": true,
|
|
3444
|
-
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/
|
|
3866
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetOrgSecretInput" } } }
|
|
3445
3867
|
},
|
|
3446
3868
|
"responses": {
|
|
3447
3869
|
"200": {
|
|
3448
3870
|
"description": "Secret updated",
|
|
3449
3871
|
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
3450
3872
|
"type": "object",
|
|
3451
|
-
"properties": { "data": { "$ref": "#/components/schemas/
|
|
3873
|
+
"properties": { "data": { "$ref": "#/components/schemas/OrgSecretWriteResult" } }
|
|
3452
3874
|
}] } } }
|
|
3453
3875
|
},
|
|
3454
3876
|
"201": {
|
|
3455
3877
|
"description": "Secret created",
|
|
3456
3878
|
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
3457
3879
|
"type": "object",
|
|
3458
|
-
"properties": { "data": { "$ref": "#/components/schemas/
|
|
3880
|
+
"properties": { "data": { "$ref": "#/components/schemas/OrgSecretWriteResult" } }
|
|
3459
3881
|
}] } } }
|
|
3460
3882
|
},
|
|
3461
3883
|
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
3462
|
-
"401": { "$ref": "#/components/responses/Unauthorized" }
|
|
3463
|
-
"404": { "$ref": "#/components/responses/NotFound" }
|
|
3884
|
+
"401": { "$ref": "#/components/responses/Unauthorized" }
|
|
3464
3885
|
}
|
|
3465
3886
|
},
|
|
3466
3887
|
"delete": {
|
|
3467
|
-
"operationId": "
|
|
3468
|
-
"summary": "Delete
|
|
3469
|
-
"description": "Removes the secret.
|
|
3888
|
+
"operationId": "deleteOrgSecret",
|
|
3889
|
+
"summary": "Delete an org secret",
|
|
3890
|
+
"description": "Removes the org secret. Functions keep the previous value until\neach is redeployed. Returns 404 if the key did not exist.\n",
|
|
3470
3891
|
"tags": ["Functions"],
|
|
3471
3892
|
"responses": {
|
|
3472
3893
|
"204": { "description": "Secret deleted" },
|
|
@@ -4428,6 +4849,177 @@ const openapiDocument = {
|
|
|
4428
4849
|
"orgs"
|
|
4429
4850
|
]
|
|
4430
4851
|
},
|
|
4852
|
+
"PlanLimits": {
|
|
4853
|
+
"type": "object",
|
|
4854
|
+
"description": "Plan-derived quota limits for an account.",
|
|
4855
|
+
"properties": {
|
|
4856
|
+
"storage_mb": { "type": "number" },
|
|
4857
|
+
"send_per_hour": { "type": "number" },
|
|
4858
|
+
"send_per_day": { "type": "number" },
|
|
4859
|
+
"api_per_minute": { "type": "number" },
|
|
4860
|
+
"webhooks_max_global": { "type": ["number", "null"] },
|
|
4861
|
+
"webhooks_per_domain": { "type": "boolean" },
|
|
4862
|
+
"filters_per_domain": { "type": "boolean" },
|
|
4863
|
+
"spam_thresholds_per_domain": { "type": "boolean" }
|
|
4864
|
+
},
|
|
4865
|
+
"required": [
|
|
4866
|
+
"storage_mb",
|
|
4867
|
+
"send_per_hour",
|
|
4868
|
+
"send_per_day",
|
|
4869
|
+
"api_per_minute",
|
|
4870
|
+
"webhooks_max_global",
|
|
4871
|
+
"webhooks_per_domain",
|
|
4872
|
+
"filters_per_domain",
|
|
4873
|
+
"spam_thresholds_per_domain"
|
|
4874
|
+
]
|
|
4875
|
+
},
|
|
4876
|
+
"CreateAgentAccountInput": {
|
|
4877
|
+
"type": "object",
|
|
4878
|
+
"additionalProperties": false,
|
|
4879
|
+
"properties": {
|
|
4880
|
+
"terms_accepted": {
|
|
4881
|
+
"type": "boolean",
|
|
4882
|
+
"enum": [true],
|
|
4883
|
+
"description": "Must be true to accept the Terms of Service and Privacy Policy."
|
|
4884
|
+
},
|
|
4885
|
+
"device_name": {
|
|
4886
|
+
"type": "string",
|
|
4887
|
+
"minLength": 1,
|
|
4888
|
+
"maxLength": 80,
|
|
4889
|
+
"description": "Optional label for the device or agent creating the account."
|
|
4890
|
+
}
|
|
4891
|
+
},
|
|
4892
|
+
"required": ["terms_accepted"]
|
|
4893
|
+
},
|
|
4894
|
+
"AgentAccountUpgradeHint": {
|
|
4895
|
+
"type": "object",
|
|
4896
|
+
"description": "In-band pointer to the upgrade path for an agent account.",
|
|
4897
|
+
"properties": {
|
|
4898
|
+
"plan": {
|
|
4899
|
+
"type": "string",
|
|
4900
|
+
"enum": ["developer"]
|
|
4901
|
+
},
|
|
4902
|
+
"description": { "type": "string" },
|
|
4903
|
+
"claim_path": { "type": "string" }
|
|
4904
|
+
},
|
|
4905
|
+
"required": [
|
|
4906
|
+
"plan",
|
|
4907
|
+
"description",
|
|
4908
|
+
"claim_path"
|
|
4909
|
+
]
|
|
4910
|
+
},
|
|
4911
|
+
"AgentAccountResult": {
|
|
4912
|
+
"type": "object",
|
|
4913
|
+
"properties": {
|
|
4914
|
+
"api_key": {
|
|
4915
|
+
"type": "string",
|
|
4916
|
+
"description": "One-time API key (prefixed `prim_`). Shown once; store it securely."
|
|
4917
|
+
},
|
|
4918
|
+
"org_id": {
|
|
4919
|
+
"type": "string",
|
|
4920
|
+
"format": "uuid"
|
|
4921
|
+
},
|
|
4922
|
+
"address": {
|
|
4923
|
+
"type": ["string", "null"],
|
|
4924
|
+
"description": "Provisioned managed inbox FQDN, or null if the inbox publish was deferred."
|
|
4925
|
+
},
|
|
4926
|
+
"plan": {
|
|
4927
|
+
"type": "string",
|
|
4928
|
+
"enum": ["agent"]
|
|
4929
|
+
},
|
|
4930
|
+
"limits": { "$ref": "#/components/schemas/PlanLimits" },
|
|
4931
|
+
"upgrade": { "$ref": "#/components/schemas/AgentAccountUpgradeHint" }
|
|
4932
|
+
},
|
|
4933
|
+
"required": [
|
|
4934
|
+
"api_key",
|
|
4935
|
+
"org_id",
|
|
4936
|
+
"address",
|
|
4937
|
+
"plan",
|
|
4938
|
+
"limits",
|
|
4939
|
+
"upgrade"
|
|
4940
|
+
]
|
|
4941
|
+
},
|
|
4942
|
+
"StartAgentClaimInput": {
|
|
4943
|
+
"type": "object",
|
|
4944
|
+
"additionalProperties": false,
|
|
4945
|
+
"properties": { "email": {
|
|
4946
|
+
"type": "string",
|
|
4947
|
+
"format": "email",
|
|
4948
|
+
"maxLength": 254,
|
|
4949
|
+
"description": "Email to confirm. Must not already belong to a Primitive account."
|
|
4950
|
+
} },
|
|
4951
|
+
"required": ["email"]
|
|
4952
|
+
},
|
|
4953
|
+
"AgentClaimStartResult": {
|
|
4954
|
+
"type": "object",
|
|
4955
|
+
"properties": {
|
|
4956
|
+
"claim_session_id": { "type": "string" },
|
|
4957
|
+
"resend_after_seconds": { "type": "integer" },
|
|
4958
|
+
"expires_in_seconds": { "type": "integer" }
|
|
4959
|
+
},
|
|
4960
|
+
"required": [
|
|
4961
|
+
"claim_session_id",
|
|
4962
|
+
"resend_after_seconds",
|
|
4963
|
+
"expires_in_seconds"
|
|
4964
|
+
]
|
|
4965
|
+
},
|
|
4966
|
+
"VerifyAgentClaimInput": {
|
|
4967
|
+
"type": "object",
|
|
4968
|
+
"additionalProperties": false,
|
|
4969
|
+
"properties": { "verification_code": {
|
|
4970
|
+
"type": "string",
|
|
4971
|
+
"minLength": 1,
|
|
4972
|
+
"maxLength": 32,
|
|
4973
|
+
"description": "The verification code emailed by the claim start step."
|
|
4974
|
+
} },
|
|
4975
|
+
"required": ["verification_code"]
|
|
4976
|
+
},
|
|
4977
|
+
"AgentClaimResult": {
|
|
4978
|
+
"type": "object",
|
|
4979
|
+
"properties": {
|
|
4980
|
+
"org_id": {
|
|
4981
|
+
"type": "string",
|
|
4982
|
+
"format": "uuid"
|
|
4983
|
+
},
|
|
4984
|
+
"plan": {
|
|
4985
|
+
"type": "string",
|
|
4986
|
+
"enum": ["developer"]
|
|
4987
|
+
},
|
|
4988
|
+
"email": {
|
|
4989
|
+
"type": "string",
|
|
4990
|
+
"format": "email"
|
|
4991
|
+
},
|
|
4992
|
+
"limits": { "$ref": "#/components/schemas/PlanLimits" }
|
|
4993
|
+
},
|
|
4994
|
+
"required": [
|
|
4995
|
+
"org_id",
|
|
4996
|
+
"plan",
|
|
4997
|
+
"email",
|
|
4998
|
+
"limits"
|
|
4999
|
+
]
|
|
5000
|
+
},
|
|
5001
|
+
"CreateAgentClaimLinkInput": {
|
|
5002
|
+
"type": "object",
|
|
5003
|
+
"additionalProperties": false,
|
|
5004
|
+
"description": "No fields; an empty object is accepted.",
|
|
5005
|
+
"properties": {}
|
|
5006
|
+
},
|
|
5007
|
+
"AgentClaimLinkResult": {
|
|
5008
|
+
"type": "object",
|
|
5009
|
+
"properties": {
|
|
5010
|
+
"claim_token": { "type": "string" },
|
|
5011
|
+
"claim_url": {
|
|
5012
|
+
"type": ["string", "null"],
|
|
5013
|
+
"description": "Browser URL to hand to a human, or null if no web origin is configured."
|
|
5014
|
+
},
|
|
5015
|
+
"expires_in_seconds": { "type": "integer" }
|
|
5016
|
+
},
|
|
5017
|
+
"required": [
|
|
5018
|
+
"claim_token",
|
|
5019
|
+
"claim_url",
|
|
5020
|
+
"expires_in_seconds"
|
|
5021
|
+
]
|
|
5022
|
+
},
|
|
4431
5023
|
"CliLogoutInput": {
|
|
4432
5024
|
"type": "object",
|
|
4433
5025
|
"additionalProperties": false,
|
|
@@ -4466,6 +5058,16 @@ const openapiDocument = {
|
|
|
4466
5058
|
},
|
|
4467
5059
|
"email": { "type": "string" },
|
|
4468
5060
|
"plan": { "type": "string" },
|
|
5061
|
+
"limits": { "$ref": "#/components/schemas/PlanLimits" },
|
|
5062
|
+
"entitlements": {
|
|
5063
|
+
"type": "array",
|
|
5064
|
+
"items": { "type": "string" },
|
|
5065
|
+
"description": "Granted org entitlement keys (sorted). A headless caller reads its\ncapabilities here — e.g. an emailless agent seeing only\n[\"send_mail\", \"send_to_known_addresses\"] knows it is reply-only.\n"
|
|
5066
|
+
},
|
|
5067
|
+
"managed_inbox_address": {
|
|
5068
|
+
"type": ["string", "null"],
|
|
5069
|
+
"description": "The managed inbox FQDN to reply as, or null if the org has no managed inbox."
|
|
5070
|
+
},
|
|
4469
5071
|
"created_at": {
|
|
4470
5072
|
"type": "string",
|
|
4471
5073
|
"format": "date-time"
|
|
@@ -4493,6 +5095,9 @@ const openapiDocument = {
|
|
|
4493
5095
|
"id",
|
|
4494
5096
|
"email",
|
|
4495
5097
|
"plan",
|
|
5098
|
+
"limits",
|
|
5099
|
+
"entitlements",
|
|
5100
|
+
"managed_inbox_address",
|
|
4496
5101
|
"created_at",
|
|
4497
5102
|
"discard_content_on_webhook_confirmed"
|
|
4498
5103
|
]
|
|
@@ -7503,6 +8108,81 @@ const openapiDocument = {
|
|
|
7503
8108
|
"updated_at",
|
|
7504
8109
|
"created"
|
|
7505
8110
|
]
|
|
8111
|
+
},
|
|
8112
|
+
"OrgSecretListItem": {
|
|
8113
|
+
"type": "object",
|
|
8114
|
+
"description": "One row from GET /org/secrets. Org secrets are always user-set\n(there are no managed org secrets), so `created_at` /\n`updated_at` are always present.\n",
|
|
8115
|
+
"properties": {
|
|
8116
|
+
"key": { "type": "string" },
|
|
8117
|
+
"created_at": {
|
|
8118
|
+
"type": "string",
|
|
8119
|
+
"format": "date-time"
|
|
8120
|
+
},
|
|
8121
|
+
"updated_at": {
|
|
8122
|
+
"type": "string",
|
|
8123
|
+
"format": "date-time"
|
|
8124
|
+
}
|
|
8125
|
+
},
|
|
8126
|
+
"required": [
|
|
8127
|
+
"key",
|
|
8128
|
+
"created_at",
|
|
8129
|
+
"updated_at"
|
|
8130
|
+
]
|
|
8131
|
+
},
|
|
8132
|
+
"CreateOrgSecretInput": {
|
|
8133
|
+
"type": "object",
|
|
8134
|
+
"additionalProperties": false,
|
|
8135
|
+
"description": "Body for POST /org/secrets.",
|
|
8136
|
+
"properties": {
|
|
8137
|
+
"key": {
|
|
8138
|
+
"type": "string",
|
|
8139
|
+
"pattern": "^[A-Z_][A-Z0-9_]*$",
|
|
8140
|
+
"description": "Uppercase letters, digits, and underscores. Must start with\na letter or underscore. System-managed keys are reserved.\n"
|
|
8141
|
+
},
|
|
8142
|
+
"value": {
|
|
8143
|
+
"type": "string",
|
|
8144
|
+
"minLength": 1,
|
|
8145
|
+
"maxLength": 4096,
|
|
8146
|
+
"description": "Secret value, up to 4096 UTF-8 bytes. Encrypted at rest.\nNever returned by any read endpoint.\n"
|
|
8147
|
+
}
|
|
8148
|
+
},
|
|
8149
|
+
"required": ["key", "value"]
|
|
8150
|
+
},
|
|
8151
|
+
"SetOrgSecretInput": {
|
|
8152
|
+
"type": "object",
|
|
8153
|
+
"additionalProperties": false,
|
|
8154
|
+
"description": "Body for PUT /org/secrets/{key}. Key comes from the path.",
|
|
8155
|
+
"properties": { "value": {
|
|
8156
|
+
"type": "string",
|
|
8157
|
+
"minLength": 1,
|
|
8158
|
+
"maxLength": 4096
|
|
8159
|
+
} },
|
|
8160
|
+
"required": ["value"]
|
|
8161
|
+
},
|
|
8162
|
+
"OrgSecretWriteResult": {
|
|
8163
|
+
"type": "object",
|
|
8164
|
+
"description": "Returned by POST and PUT org secret routes.",
|
|
8165
|
+
"properties": {
|
|
8166
|
+
"key": { "type": "string" },
|
|
8167
|
+
"created_at": {
|
|
8168
|
+
"type": "string",
|
|
8169
|
+
"format": "date-time"
|
|
8170
|
+
},
|
|
8171
|
+
"updated_at": {
|
|
8172
|
+
"type": "string",
|
|
8173
|
+
"format": "date-time"
|
|
8174
|
+
},
|
|
8175
|
+
"created": {
|
|
8176
|
+
"type": "boolean",
|
|
8177
|
+
"description": "True if this call inserted a new row, false if it updated an existing one."
|
|
8178
|
+
}
|
|
8179
|
+
},
|
|
8180
|
+
"required": [
|
|
8181
|
+
"key",
|
|
8182
|
+
"created_at",
|
|
8183
|
+
"updated_at",
|
|
8184
|
+
"created"
|
|
8185
|
+
]
|
|
7506
8186
|
}
|
|
7507
8187
|
}
|
|
7508
8188
|
}
|
|
@@ -7531,6 +8211,39 @@ const operationManifest = [
|
|
|
7531
8211
|
},
|
|
7532
8212
|
"email": { "type": "string" },
|
|
7533
8213
|
"plan": { "type": "string" },
|
|
8214
|
+
"limits": {
|
|
8215
|
+
"type": "object",
|
|
8216
|
+
"description": "Plan-derived quota limits for an account.",
|
|
8217
|
+
"properties": {
|
|
8218
|
+
"storage_mb": { "type": "number" },
|
|
8219
|
+
"send_per_hour": { "type": "number" },
|
|
8220
|
+
"send_per_day": { "type": "number" },
|
|
8221
|
+
"api_per_minute": { "type": "number" },
|
|
8222
|
+
"webhooks_max_global": { "type": ["number", "null"] },
|
|
8223
|
+
"webhooks_per_domain": { "type": "boolean" },
|
|
8224
|
+
"filters_per_domain": { "type": "boolean" },
|
|
8225
|
+
"spam_thresholds_per_domain": { "type": "boolean" }
|
|
8226
|
+
},
|
|
8227
|
+
"required": [
|
|
8228
|
+
"storage_mb",
|
|
8229
|
+
"send_per_hour",
|
|
8230
|
+
"send_per_day",
|
|
8231
|
+
"api_per_minute",
|
|
8232
|
+
"webhooks_max_global",
|
|
8233
|
+
"webhooks_per_domain",
|
|
8234
|
+
"filters_per_domain",
|
|
8235
|
+
"spam_thresholds_per_domain"
|
|
8236
|
+
]
|
|
8237
|
+
},
|
|
8238
|
+
"entitlements": {
|
|
8239
|
+
"type": "array",
|
|
8240
|
+
"items": { "type": "string" },
|
|
8241
|
+
"description": "Granted org entitlement keys (sorted). A headless caller reads its\ncapabilities here — e.g. an emailless agent seeing only\n[\"send_mail\", \"send_to_known_addresses\"] knows it is reply-only.\n"
|
|
8242
|
+
},
|
|
8243
|
+
"managed_inbox_address": {
|
|
8244
|
+
"type": ["string", "null"],
|
|
8245
|
+
"description": "The managed inbox FQDN to reply as, or null if the org has no managed inbox."
|
|
8246
|
+
},
|
|
7534
8247
|
"created_at": {
|
|
7535
8248
|
"type": "string",
|
|
7536
8249
|
"format": "date-time"
|
|
@@ -7558,6 +8271,9 @@ const operationManifest = [
|
|
|
7558
8271
|
"id",
|
|
7559
8272
|
"email",
|
|
7560
8273
|
"plan",
|
|
8274
|
+
"limits",
|
|
8275
|
+
"entitlements",
|
|
8276
|
+
"managed_inbox_address",
|
|
7561
8277
|
"created_at",
|
|
7562
8278
|
"discard_content_on_webhook_confirmed"
|
|
7563
8279
|
]
|
|
@@ -7686,46 +8402,188 @@ const operationManifest = [
|
|
|
7686
8402
|
"type": "object",
|
|
7687
8403
|
"additionalProperties": false,
|
|
7688
8404
|
"properties": {
|
|
7689
|
-
"spam_threshold": {
|
|
7690
|
-
"type": ["number", "null"],
|
|
7691
|
-
"minimum": 0,
|
|
7692
|
-
"maximum": 15,
|
|
7693
|
-
"description": "Global spam score threshold (0-15). Emails scoring above this are rejected. Set to null to disable."
|
|
7694
|
-
},
|
|
7695
|
-
"discard_content_on_webhook_confirmed": {
|
|
8405
|
+
"spam_threshold": {
|
|
8406
|
+
"type": ["number", "null"],
|
|
8407
|
+
"minimum": 0,
|
|
8408
|
+
"maximum": 15,
|
|
8409
|
+
"description": "Global spam score threshold (0-15). Emails scoring above this are rejected. Set to null to disable."
|
|
8410
|
+
},
|
|
8411
|
+
"discard_content_on_webhook_confirmed": {
|
|
8412
|
+
"type": "boolean",
|
|
8413
|
+
"description": "Whether to discard email content after the webhook endpoint confirms receipt."
|
|
8414
|
+
}
|
|
8415
|
+
},
|
|
8416
|
+
"minProperties": 1
|
|
8417
|
+
},
|
|
8418
|
+
"responseSchema": {
|
|
8419
|
+
"type": "object",
|
|
8420
|
+
"properties": {
|
|
8421
|
+
"id": {
|
|
8422
|
+
"type": "string",
|
|
8423
|
+
"format": "uuid"
|
|
8424
|
+
},
|
|
8425
|
+
"email": { "type": "string" },
|
|
8426
|
+
"plan": { "type": "string" },
|
|
8427
|
+
"spam_threshold": {
|
|
8428
|
+
"type": ["number", "null"],
|
|
8429
|
+
"minimum": 0,
|
|
8430
|
+
"maximum": 15
|
|
8431
|
+
},
|
|
8432
|
+
"discard_content_on_webhook_confirmed": { "type": "boolean" }
|
|
8433
|
+
},
|
|
8434
|
+
"required": [
|
|
8435
|
+
"id",
|
|
8436
|
+
"email",
|
|
8437
|
+
"plan",
|
|
8438
|
+
"discard_content_on_webhook_confirmed"
|
|
8439
|
+
]
|
|
8440
|
+
},
|
|
8441
|
+
"sdkName": "updateAccount",
|
|
8442
|
+
"summary": "Update account settings",
|
|
8443
|
+
"tag": "Account",
|
|
8444
|
+
"tagCommand": "account"
|
|
8445
|
+
},
|
|
8446
|
+
{
|
|
8447
|
+
"binaryResponse": false,
|
|
8448
|
+
"bodyRequired": true,
|
|
8449
|
+
"command": "create-agent-account",
|
|
8450
|
+
"description": "Creates an emailless agent account without authentication and returns a\none-time API key (prefixed `prim_`) plus a provisioned managed inbox.\nThe account is on the `agent` plan: reply-only (it can send only to\naddresses that have already sent it authenticated mail) with tight send\nlimits. Use the returned `api_key` as a Bearer token on later calls. The\naccount can be upgraded to a full developer account by confirming an\nemail through the claim flow. This endpoint does not require an API key.\n",
|
|
8451
|
+
"hasJsonBody": true,
|
|
8452
|
+
"method": "POST",
|
|
8453
|
+
"operationId": "createAgentAccount",
|
|
8454
|
+
"path": "/agent/accounts",
|
|
8455
|
+
"pathParams": [],
|
|
8456
|
+
"queryParams": [],
|
|
8457
|
+
"requestSchema": {
|
|
8458
|
+
"type": "object",
|
|
8459
|
+
"additionalProperties": false,
|
|
8460
|
+
"properties": {
|
|
8461
|
+
"terms_accepted": {
|
|
7696
8462
|
"type": "boolean",
|
|
7697
|
-
"
|
|
8463
|
+
"enum": [true],
|
|
8464
|
+
"description": "Must be true to accept the Terms of Service and Privacy Policy."
|
|
8465
|
+
},
|
|
8466
|
+
"device_name": {
|
|
8467
|
+
"type": "string",
|
|
8468
|
+
"minLength": 1,
|
|
8469
|
+
"maxLength": 80,
|
|
8470
|
+
"description": "Optional label for the device or agent creating the account."
|
|
7698
8471
|
}
|
|
7699
8472
|
},
|
|
7700
|
-
"
|
|
8473
|
+
"required": ["terms_accepted"]
|
|
7701
8474
|
},
|
|
7702
8475
|
"responseSchema": {
|
|
7703
8476
|
"type": "object",
|
|
7704
8477
|
"properties": {
|
|
7705
|
-
"
|
|
8478
|
+
"api_key": {
|
|
8479
|
+
"type": "string",
|
|
8480
|
+
"description": "One-time API key (prefixed `prim_`). Shown once; store it securely."
|
|
8481
|
+
},
|
|
8482
|
+
"org_id": {
|
|
7706
8483
|
"type": "string",
|
|
7707
8484
|
"format": "uuid"
|
|
7708
8485
|
},
|
|
7709
|
-
"
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
"type": ["number", "null"],
|
|
7713
|
-
"minimum": 0,
|
|
7714
|
-
"maximum": 15
|
|
8486
|
+
"address": {
|
|
8487
|
+
"type": ["string", "null"],
|
|
8488
|
+
"description": "Provisioned managed inbox FQDN, or null if the inbox publish was deferred."
|
|
7715
8489
|
},
|
|
7716
|
-
"
|
|
8490
|
+
"plan": {
|
|
8491
|
+
"type": "string",
|
|
8492
|
+
"enum": ["agent"]
|
|
8493
|
+
},
|
|
8494
|
+
"limits": {
|
|
8495
|
+
"type": "object",
|
|
8496
|
+
"description": "Plan-derived quota limits for an account.",
|
|
8497
|
+
"properties": {
|
|
8498
|
+
"storage_mb": { "type": "number" },
|
|
8499
|
+
"send_per_hour": { "type": "number" },
|
|
8500
|
+
"send_per_day": { "type": "number" },
|
|
8501
|
+
"api_per_minute": { "type": "number" },
|
|
8502
|
+
"webhooks_max_global": { "type": ["number", "null"] },
|
|
8503
|
+
"webhooks_per_domain": { "type": "boolean" },
|
|
8504
|
+
"filters_per_domain": { "type": "boolean" },
|
|
8505
|
+
"spam_thresholds_per_domain": { "type": "boolean" }
|
|
8506
|
+
},
|
|
8507
|
+
"required": [
|
|
8508
|
+
"storage_mb",
|
|
8509
|
+
"send_per_hour",
|
|
8510
|
+
"send_per_day",
|
|
8511
|
+
"api_per_minute",
|
|
8512
|
+
"webhooks_max_global",
|
|
8513
|
+
"webhooks_per_domain",
|
|
8514
|
+
"filters_per_domain",
|
|
8515
|
+
"spam_thresholds_per_domain"
|
|
8516
|
+
]
|
|
8517
|
+
},
|
|
8518
|
+
"upgrade": {
|
|
8519
|
+
"type": "object",
|
|
8520
|
+
"description": "In-band pointer to the upgrade path for an agent account.",
|
|
8521
|
+
"properties": {
|
|
8522
|
+
"plan": {
|
|
8523
|
+
"type": "string",
|
|
8524
|
+
"enum": ["developer"]
|
|
8525
|
+
},
|
|
8526
|
+
"description": { "type": "string" },
|
|
8527
|
+
"claim_path": { "type": "string" }
|
|
8528
|
+
},
|
|
8529
|
+
"required": [
|
|
8530
|
+
"plan",
|
|
8531
|
+
"description",
|
|
8532
|
+
"claim_path"
|
|
8533
|
+
]
|
|
8534
|
+
}
|
|
7717
8535
|
},
|
|
7718
8536
|
"required": [
|
|
7719
|
-
"
|
|
7720
|
-
"
|
|
8537
|
+
"api_key",
|
|
8538
|
+
"org_id",
|
|
8539
|
+
"address",
|
|
7721
8540
|
"plan",
|
|
7722
|
-
"
|
|
8541
|
+
"limits",
|
|
8542
|
+
"upgrade"
|
|
7723
8543
|
]
|
|
7724
8544
|
},
|
|
7725
|
-
"sdkName": "
|
|
7726
|
-
"summary": "
|
|
7727
|
-
"tag": "
|
|
7728
|
-
"tagCommand": "
|
|
8545
|
+
"sdkName": "createAgentAccount",
|
|
8546
|
+
"summary": "Create an emailless agent account",
|
|
8547
|
+
"tag": "Agent",
|
|
8548
|
+
"tagCommand": "agent"
|
|
8549
|
+
},
|
|
8550
|
+
{
|
|
8551
|
+
"binaryResponse": false,
|
|
8552
|
+
"bodyRequired": false,
|
|
8553
|
+
"command": "create-agent-claim-link",
|
|
8554
|
+
"description": "Mints an opaque, single-use link an agent can hand to a human to\ncomplete the email-confirmation upgrade in a browser. Authenticated by\nthe agent's own API key. `claim_url` is null when the API host cannot\nresolve a web origin to build the link.\n",
|
|
8555
|
+
"hasJsonBody": true,
|
|
8556
|
+
"method": "POST",
|
|
8557
|
+
"operationId": "createAgentClaimLink",
|
|
8558
|
+
"path": "/agent/claim/link",
|
|
8559
|
+
"pathParams": [],
|
|
8560
|
+
"queryParams": [],
|
|
8561
|
+
"requestSchema": {
|
|
8562
|
+
"type": "object",
|
|
8563
|
+
"additionalProperties": false,
|
|
8564
|
+
"description": "No fields; an empty object is accepted.",
|
|
8565
|
+
"properties": {}
|
|
8566
|
+
},
|
|
8567
|
+
"responseSchema": {
|
|
8568
|
+
"type": "object",
|
|
8569
|
+
"properties": {
|
|
8570
|
+
"claim_token": { "type": "string" },
|
|
8571
|
+
"claim_url": {
|
|
8572
|
+
"type": ["string", "null"],
|
|
8573
|
+
"description": "Browser URL to hand to a human, or null if no web origin is configured."
|
|
8574
|
+
},
|
|
8575
|
+
"expires_in_seconds": { "type": "integer" }
|
|
8576
|
+
},
|
|
8577
|
+
"required": [
|
|
8578
|
+
"claim_token",
|
|
8579
|
+
"claim_url",
|
|
8580
|
+
"expires_in_seconds"
|
|
8581
|
+
]
|
|
8582
|
+
},
|
|
8583
|
+
"sdkName": "createAgentClaimLink",
|
|
8584
|
+
"summary": "Create a browser claim link",
|
|
8585
|
+
"tag": "Agent",
|
|
8586
|
+
"tagCommand": "agent"
|
|
7729
8587
|
},
|
|
7730
8588
|
{
|
|
7731
8589
|
"binaryResponse": false,
|
|
@@ -7779,6 +8637,46 @@ const operationManifest = [
|
|
|
7779
8637
|
"tag": "Agent",
|
|
7780
8638
|
"tagCommand": "agent"
|
|
7781
8639
|
},
|
|
8640
|
+
{
|
|
8641
|
+
"binaryResponse": false,
|
|
8642
|
+
"bodyRequired": true,
|
|
8643
|
+
"command": "start-agent-claim",
|
|
8644
|
+
"description": "Begins upgrading an emailless `agent` account into a full `developer`\naccount by confirming an email address. Authenticated by the agent's own\nAPI key (the org is taken from the credential). Sends a verification\ncode to the supplied email and returns the claim session id plus resend\ntiming. Submit the code to `/agent/claim/verify` to complete the\nupgrade. Confirming an email that already belongs to a Primitive account\nis rejected.\n",
|
|
8645
|
+
"hasJsonBody": true,
|
|
8646
|
+
"method": "POST",
|
|
8647
|
+
"operationId": "startAgentClaim",
|
|
8648
|
+
"path": "/agent/claim/start",
|
|
8649
|
+
"pathParams": [],
|
|
8650
|
+
"queryParams": [],
|
|
8651
|
+
"requestSchema": {
|
|
8652
|
+
"type": "object",
|
|
8653
|
+
"additionalProperties": false,
|
|
8654
|
+
"properties": { "email": {
|
|
8655
|
+
"type": "string",
|
|
8656
|
+
"format": "email",
|
|
8657
|
+
"maxLength": 254,
|
|
8658
|
+
"description": "Email to confirm. Must not already belong to a Primitive account."
|
|
8659
|
+
} },
|
|
8660
|
+
"required": ["email"]
|
|
8661
|
+
},
|
|
8662
|
+
"responseSchema": {
|
|
8663
|
+
"type": "object",
|
|
8664
|
+
"properties": {
|
|
8665
|
+
"claim_session_id": { "type": "string" },
|
|
8666
|
+
"resend_after_seconds": { "type": "integer" },
|
|
8667
|
+
"expires_in_seconds": { "type": "integer" }
|
|
8668
|
+
},
|
|
8669
|
+
"required": [
|
|
8670
|
+
"claim_session_id",
|
|
8671
|
+
"resend_after_seconds",
|
|
8672
|
+
"expires_in_seconds"
|
|
8673
|
+
]
|
|
8674
|
+
},
|
|
8675
|
+
"sdkName": "startAgentClaim",
|
|
8676
|
+
"summary": "Start an agent account email claim",
|
|
8677
|
+
"tag": "Agent",
|
|
8678
|
+
"tagCommand": "agent"
|
|
8679
|
+
},
|
|
7782
8680
|
{
|
|
7783
8681
|
"binaryResponse": false,
|
|
7784
8682
|
"bodyRequired": true,
|
|
@@ -7861,6 +8759,80 @@ const operationManifest = [
|
|
|
7861
8759
|
"tag": "Agent",
|
|
7862
8760
|
"tagCommand": "agent"
|
|
7863
8761
|
},
|
|
8762
|
+
{
|
|
8763
|
+
"binaryResponse": false,
|
|
8764
|
+
"bodyRequired": true,
|
|
8765
|
+
"command": "verify-agent-claim",
|
|
8766
|
+
"description": "Confirms the verification code emailed by `/agent/claim/start` and\nupgrades the account to the `developer` plan. The org id, API key, and\nmanaged inbox all carry over; the send cap lifts. Authenticated by the\nagent's own API key.\n",
|
|
8767
|
+
"hasJsonBody": true,
|
|
8768
|
+
"method": "POST",
|
|
8769
|
+
"operationId": "verifyAgentClaim",
|
|
8770
|
+
"path": "/agent/claim/verify",
|
|
8771
|
+
"pathParams": [],
|
|
8772
|
+
"queryParams": [],
|
|
8773
|
+
"requestSchema": {
|
|
8774
|
+
"type": "object",
|
|
8775
|
+
"additionalProperties": false,
|
|
8776
|
+
"properties": { "verification_code": {
|
|
8777
|
+
"type": "string",
|
|
8778
|
+
"minLength": 1,
|
|
8779
|
+
"maxLength": 32,
|
|
8780
|
+
"description": "The verification code emailed by the claim start step."
|
|
8781
|
+
} },
|
|
8782
|
+
"required": ["verification_code"]
|
|
8783
|
+
},
|
|
8784
|
+
"responseSchema": {
|
|
8785
|
+
"type": "object",
|
|
8786
|
+
"properties": {
|
|
8787
|
+
"org_id": {
|
|
8788
|
+
"type": "string",
|
|
8789
|
+
"format": "uuid"
|
|
8790
|
+
},
|
|
8791
|
+
"plan": {
|
|
8792
|
+
"type": "string",
|
|
8793
|
+
"enum": ["developer"]
|
|
8794
|
+
},
|
|
8795
|
+
"email": {
|
|
8796
|
+
"type": "string",
|
|
8797
|
+
"format": "email"
|
|
8798
|
+
},
|
|
8799
|
+
"limits": {
|
|
8800
|
+
"type": "object",
|
|
8801
|
+
"description": "Plan-derived quota limits for an account.",
|
|
8802
|
+
"properties": {
|
|
8803
|
+
"storage_mb": { "type": "number" },
|
|
8804
|
+
"send_per_hour": { "type": "number" },
|
|
8805
|
+
"send_per_day": { "type": "number" },
|
|
8806
|
+
"api_per_minute": { "type": "number" },
|
|
8807
|
+
"webhooks_max_global": { "type": ["number", "null"] },
|
|
8808
|
+
"webhooks_per_domain": { "type": "boolean" },
|
|
8809
|
+
"filters_per_domain": { "type": "boolean" },
|
|
8810
|
+
"spam_thresholds_per_domain": { "type": "boolean" }
|
|
8811
|
+
},
|
|
8812
|
+
"required": [
|
|
8813
|
+
"storage_mb",
|
|
8814
|
+
"send_per_hour",
|
|
8815
|
+
"send_per_day",
|
|
8816
|
+
"api_per_minute",
|
|
8817
|
+
"webhooks_max_global",
|
|
8818
|
+
"webhooks_per_domain",
|
|
8819
|
+
"filters_per_domain",
|
|
8820
|
+
"spam_thresholds_per_domain"
|
|
8821
|
+
]
|
|
8822
|
+
}
|
|
8823
|
+
},
|
|
8824
|
+
"required": [
|
|
8825
|
+
"org_id",
|
|
8826
|
+
"plan",
|
|
8827
|
+
"email",
|
|
8828
|
+
"limits"
|
|
8829
|
+
]
|
|
8830
|
+
},
|
|
8831
|
+
"sdkName": "verifyAgentClaim",
|
|
8832
|
+
"summary": "Verify an agent account email claim",
|
|
8833
|
+
"tag": "Agent",
|
|
8834
|
+
"tagCommand": "agent"
|
|
8835
|
+
},
|
|
7864
8836
|
{
|
|
7865
8837
|
"binaryResponse": false,
|
|
7866
8838
|
"bodyRequired": true,
|
|
@@ -9758,6 +10730,22 @@ const operationManifest = [
|
|
|
9758
10730
|
"name": "date_to",
|
|
9759
10731
|
"required": false,
|
|
9760
10732
|
"type": "string"
|
|
10733
|
+
},
|
|
10734
|
+
{
|
|
10735
|
+
"description": "Forward-tail cursor. Returns rows that became visible AFTER this\ncursor, oldest-first, so a caller can stream new inbound mail by\nre-passing the cursor from each response. Mutually exclusive with\n`cursor` (which pages history newest-first). Pass the `meta.cursor`\nfrom the previous `since` response; an empty page means caught up.\n",
|
|
10736
|
+
"enum": null,
|
|
10737
|
+
"name": "since",
|
|
10738
|
+
"required": false,
|
|
10739
|
+
"type": "string"
|
|
10740
|
+
},
|
|
10741
|
+
{
|
|
10742
|
+
"description": "Long-poll: hold the request up to this many seconds waiting for new\nmail past `since`, returning as soon as any arrives (or an empty\npage when the wait elapses). Requires `since`. Omitted means no wait\n(returns immediately); the server treats an absent value as 0. NOT\ngiven an OpenAPI `default` on purpose: a default makes some\ngenerators (e.g. openapi-python-client) send `wait=0` on every call,\nwhich then fails the `wait` requires `since` check for plain history\nlistings.\n",
|
|
10743
|
+
"enum": null,
|
|
10744
|
+
"maximum": 30,
|
|
10745
|
+
"minimum": 0,
|
|
10746
|
+
"name": "wait",
|
|
10747
|
+
"required": false,
|
|
10748
|
+
"type": "integer"
|
|
9761
10749
|
}
|
|
9762
10750
|
],
|
|
9763
10751
|
"requestSchema": null,
|
|
@@ -10767,7 +11755,7 @@ const operationManifest = [
|
|
|
10767
11755
|
"binaryResponse": false,
|
|
10768
11756
|
"bodyRequired": true,
|
|
10769
11757
|
"command": "create-function",
|
|
10770
|
-
"description": "Creates and deploys a new function. The handler must be a single\nESM module whose default export is an object with an async\n`fetch(request, env)` method (Workers-style). Primitive signs\neach delivery and forwards the `Primitive-Signature` header to\nthe handler. Verify the raw request body with\n`PRIMITIVE_WEBHOOK_SECRET` before parsing JSON; after verification\nthe request body parses to
|
|
11758
|
+
"description": "Creates and deploys a new function. The handler must be a single\nESM module whose default export is an object with an async\n`fetch(request, env)` method (Workers-style). Primitive signs\neach delivery and forwards the `Primitive-Signature` header to\nthe handler. Verify the raw request body with\n`PRIMITIVE_WEBHOOK_SECRET` before parsing JSON; after verification\nthe request body parses to a webhook event whose `event` field is\n`email.received` for normal inbound mail, or a machine-mail type\n(`email.bounced`, `email.tls_report`, `email.dmarc_report`,\n`email.dmarc_failure`) for bounces and reports. Code is bundled\nbefore being uploaded; ship a single self-contained file rather\nthan relying on external imports.\n\n**Code limits.** `code` is capped at 1 MiB UTF-8. `sourceMap`\n(optional) is capped at 5 MiB UTF-8, stored with each deployment\nattempt, and sent to the runtime so stack traces can resolve to\noriginal source files.\n\n**Routing.** On successful deploy, the function code is live\nin the runtime, but inbound mail will not reach it until at\nleast one route is bound. Routes are managed from the Primitive\ndashboard. A `deploy_status` of `deployed` means the script is\ninstalled, not that the function is receiving mail. The\ninternal runtime URL is not returned by the API and is not a\ncustomer-facing integration surface.\n\n**Secrets.** New functions ship with the managed secrets\n(`PRIMITIVE_WEBHOOK_SECRET`, `PRIMITIVE_API_KEY`,\n`PRIMITIVE_API_BASE_URL`) already bound. Add user-set secrets via\n`POST /functions/{id}/secrets`; secret writes only land in the\nrunning handler on the next redeploy.\n",
|
|
10771
11759
|
"hasJsonBody": true,
|
|
10772
11760
|
"method": "POST",
|
|
10773
11761
|
"operationId": "createFunction",
|
|
@@ -10899,6 +11887,66 @@ const operationManifest = [
|
|
|
10899
11887
|
"tag": "Functions",
|
|
10900
11888
|
"tagCommand": "functions"
|
|
10901
11889
|
},
|
|
11890
|
+
{
|
|
11891
|
+
"binaryResponse": false,
|
|
11892
|
+
"bodyRequired": true,
|
|
11893
|
+
"command": "create-org-secret",
|
|
11894
|
+
"description": "Idempotent insert-or-update keyed on `(org_id, key)`. Returns\n201 the first time the key is set, 200 on subsequent updates.\nValues are encrypted at rest. A changed value lands in a\nfunction only on that function's next deploy.\n\nKeys must match `^[A-Z_][A-Z0-9_]*$` (uppercase letters,\ndigits, underscores; first character is a letter or\nunderscore). Values are at most 4096 UTF-8 bytes. System-\nmanaged keys are reserved and rejected.\n",
|
|
11895
|
+
"hasJsonBody": true,
|
|
11896
|
+
"method": "POST",
|
|
11897
|
+
"operationId": "createOrgSecret",
|
|
11898
|
+
"path": "/org/secrets",
|
|
11899
|
+
"pathParams": [],
|
|
11900
|
+
"queryParams": [],
|
|
11901
|
+
"requestSchema": {
|
|
11902
|
+
"type": "object",
|
|
11903
|
+
"additionalProperties": false,
|
|
11904
|
+
"description": "Body for POST /org/secrets.",
|
|
11905
|
+
"properties": {
|
|
11906
|
+
"key": {
|
|
11907
|
+
"type": "string",
|
|
11908
|
+
"pattern": "^[A-Z_][A-Z0-9_]*$",
|
|
11909
|
+
"description": "Uppercase letters, digits, and underscores. Must start with\na letter or underscore. System-managed keys are reserved.\n"
|
|
11910
|
+
},
|
|
11911
|
+
"value": {
|
|
11912
|
+
"type": "string",
|
|
11913
|
+
"minLength": 1,
|
|
11914
|
+
"maxLength": 4096,
|
|
11915
|
+
"description": "Secret value, up to 4096 UTF-8 bytes. Encrypted at rest.\nNever returned by any read endpoint.\n"
|
|
11916
|
+
}
|
|
11917
|
+
},
|
|
11918
|
+
"required": ["key", "value"]
|
|
11919
|
+
},
|
|
11920
|
+
"responseSchema": {
|
|
11921
|
+
"type": "object",
|
|
11922
|
+
"description": "Returned by POST and PUT org secret routes.",
|
|
11923
|
+
"properties": {
|
|
11924
|
+
"key": { "type": "string" },
|
|
11925
|
+
"created_at": {
|
|
11926
|
+
"type": "string",
|
|
11927
|
+
"format": "date-time"
|
|
11928
|
+
},
|
|
11929
|
+
"updated_at": {
|
|
11930
|
+
"type": "string",
|
|
11931
|
+
"format": "date-time"
|
|
11932
|
+
},
|
|
11933
|
+
"created": {
|
|
11934
|
+
"type": "boolean",
|
|
11935
|
+
"description": "True if this call inserted a new row, false if it updated an existing one."
|
|
11936
|
+
}
|
|
11937
|
+
},
|
|
11938
|
+
"required": [
|
|
11939
|
+
"key",
|
|
11940
|
+
"created_at",
|
|
11941
|
+
"updated_at",
|
|
11942
|
+
"created"
|
|
11943
|
+
]
|
|
11944
|
+
},
|
|
11945
|
+
"sdkName": "createOrgSecret",
|
|
11946
|
+
"summary": "Create or update an org secret",
|
|
11947
|
+
"tag": "Functions",
|
|
11948
|
+
"tagCommand": "functions"
|
|
11949
|
+
},
|
|
10902
11950
|
{
|
|
10903
11951
|
"binaryResponse": false,
|
|
10904
11952
|
"bodyRequired": false,
|
|
@@ -10953,6 +12001,30 @@ const operationManifest = [
|
|
|
10953
12001
|
"tag": "Functions",
|
|
10954
12002
|
"tagCommand": "functions"
|
|
10955
12003
|
},
|
|
12004
|
+
{
|
|
12005
|
+
"binaryResponse": false,
|
|
12006
|
+
"bodyRequired": false,
|
|
12007
|
+
"command": "delete-org-secret",
|
|
12008
|
+
"description": "Removes the org secret. Functions keep the previous value until\neach is redeployed. Returns 404 if the key did not exist.\n",
|
|
12009
|
+
"hasJsonBody": false,
|
|
12010
|
+
"method": "DELETE",
|
|
12011
|
+
"operationId": "deleteOrgSecret",
|
|
12012
|
+
"path": "/org/secrets/{key}",
|
|
12013
|
+
"pathParams": [{
|
|
12014
|
+
"description": "Secret key. Must match `^[A-Z_][A-Z0-9_]*$`.",
|
|
12015
|
+
"enum": null,
|
|
12016
|
+
"name": "key",
|
|
12017
|
+
"required": true,
|
|
12018
|
+
"type": "string"
|
|
12019
|
+
}],
|
|
12020
|
+
"queryParams": [],
|
|
12021
|
+
"requestSchema": null,
|
|
12022
|
+
"responseSchema": null,
|
|
12023
|
+
"sdkName": "deleteOrgSecret",
|
|
12024
|
+
"summary": "Delete an org secret",
|
|
12025
|
+
"tag": "Functions",
|
|
12026
|
+
"tagCommand": "functions"
|
|
12027
|
+
},
|
|
10956
12028
|
{
|
|
10957
12029
|
"binaryResponse": false,
|
|
10958
12030
|
"bodyRequired": false,
|
|
@@ -11828,8 +12900,52 @@ const operationManifest = [
|
|
|
11828
12900
|
]
|
|
11829
12901
|
}
|
|
11830
12902
|
},
|
|
11831
|
-
"sdkName": "listFunctions",
|
|
11832
|
-
"summary": "List functions",
|
|
12903
|
+
"sdkName": "listFunctions",
|
|
12904
|
+
"summary": "List functions",
|
|
12905
|
+
"tag": "Functions",
|
|
12906
|
+
"tagCommand": "functions"
|
|
12907
|
+
},
|
|
12908
|
+
{
|
|
12909
|
+
"binaryResponse": false,
|
|
12910
|
+
"bodyRequired": false,
|
|
12911
|
+
"command": "list-org-secrets",
|
|
12912
|
+
"description": "Returns metadata for every org-level secret. Org secrets apply\nto every function in the org and are read as `env.<KEY>` in\nhandlers. **Values are never returned.** Secret writes are\nwrite-only. A function-level secret of the same name overrides\nthe org-level value for that function.\n",
|
|
12913
|
+
"hasJsonBody": false,
|
|
12914
|
+
"method": "GET",
|
|
12915
|
+
"operationId": "listOrgSecrets",
|
|
12916
|
+
"path": "/org/secrets",
|
|
12917
|
+
"pathParams": [],
|
|
12918
|
+
"queryParams": [],
|
|
12919
|
+
"requestSchema": null,
|
|
12920
|
+
"responseSchema": {
|
|
12921
|
+
"type": "object",
|
|
12922
|
+
"properties": { "items": {
|
|
12923
|
+
"type": "array",
|
|
12924
|
+
"items": {
|
|
12925
|
+
"type": "object",
|
|
12926
|
+
"description": "One row from GET /org/secrets. Org secrets are always user-set\n(there are no managed org secrets), so `created_at` /\n`updated_at` are always present.\n",
|
|
12927
|
+
"properties": {
|
|
12928
|
+
"key": { "type": "string" },
|
|
12929
|
+
"created_at": {
|
|
12930
|
+
"type": "string",
|
|
12931
|
+
"format": "date-time"
|
|
12932
|
+
},
|
|
12933
|
+
"updated_at": {
|
|
12934
|
+
"type": "string",
|
|
12935
|
+
"format": "date-time"
|
|
12936
|
+
}
|
|
12937
|
+
},
|
|
12938
|
+
"required": [
|
|
12939
|
+
"key",
|
|
12940
|
+
"created_at",
|
|
12941
|
+
"updated_at"
|
|
12942
|
+
]
|
|
12943
|
+
}
|
|
12944
|
+
} },
|
|
12945
|
+
"required": ["items"]
|
|
12946
|
+
},
|
|
12947
|
+
"sdkName": "listOrgSecrets",
|
|
12948
|
+
"summary": "List org-level (global) secrets",
|
|
11833
12949
|
"tag": "Functions",
|
|
11834
12950
|
"tagCommand": "functions"
|
|
11835
12951
|
},
|
|
@@ -12021,6 +13137,64 @@ const operationManifest = [
|
|
|
12021
13137
|
"tag": "Functions",
|
|
12022
13138
|
"tagCommand": "functions"
|
|
12023
13139
|
},
|
|
13140
|
+
{
|
|
13141
|
+
"binaryResponse": false,
|
|
13142
|
+
"bodyRequired": true,
|
|
13143
|
+
"command": "set-org-secret",
|
|
13144
|
+
"description": "Path-keyed companion to `POST /org/secrets`. Idempotent:\nreturns 201 the first time the key is set, 200 on subsequent\nupdates. Same validation and write-only guarantees as POST.\n",
|
|
13145
|
+
"hasJsonBody": true,
|
|
13146
|
+
"method": "PUT",
|
|
13147
|
+
"operationId": "setOrgSecret",
|
|
13148
|
+
"path": "/org/secrets/{key}",
|
|
13149
|
+
"pathParams": [{
|
|
13150
|
+
"description": "Secret key. Must match `^[A-Z_][A-Z0-9_]*$`.",
|
|
13151
|
+
"enum": null,
|
|
13152
|
+
"name": "key",
|
|
13153
|
+
"required": true,
|
|
13154
|
+
"type": "string"
|
|
13155
|
+
}],
|
|
13156
|
+
"queryParams": [],
|
|
13157
|
+
"requestSchema": {
|
|
13158
|
+
"type": "object",
|
|
13159
|
+
"additionalProperties": false,
|
|
13160
|
+
"description": "Body for PUT /org/secrets/{key}. Key comes from the path.",
|
|
13161
|
+
"properties": { "value": {
|
|
13162
|
+
"type": "string",
|
|
13163
|
+
"minLength": 1,
|
|
13164
|
+
"maxLength": 4096
|
|
13165
|
+
} },
|
|
13166
|
+
"required": ["value"]
|
|
13167
|
+
},
|
|
13168
|
+
"responseSchema": {
|
|
13169
|
+
"type": "object",
|
|
13170
|
+
"description": "Returned by POST and PUT org secret routes.",
|
|
13171
|
+
"properties": {
|
|
13172
|
+
"key": { "type": "string" },
|
|
13173
|
+
"created_at": {
|
|
13174
|
+
"type": "string",
|
|
13175
|
+
"format": "date-time"
|
|
13176
|
+
},
|
|
13177
|
+
"updated_at": {
|
|
13178
|
+
"type": "string",
|
|
13179
|
+
"format": "date-time"
|
|
13180
|
+
},
|
|
13181
|
+
"created": {
|
|
13182
|
+
"type": "boolean",
|
|
13183
|
+
"description": "True if this call inserted a new row, false if it updated an existing one."
|
|
13184
|
+
}
|
|
13185
|
+
},
|
|
13186
|
+
"required": [
|
|
13187
|
+
"key",
|
|
13188
|
+
"created_at",
|
|
13189
|
+
"updated_at",
|
|
13190
|
+
"created"
|
|
13191
|
+
]
|
|
13192
|
+
},
|
|
13193
|
+
"sdkName": "setOrgSecret",
|
|
13194
|
+
"summary": "Set an org secret by key",
|
|
13195
|
+
"tag": "Functions",
|
|
13196
|
+
"tagCommand": "functions"
|
|
13197
|
+
},
|
|
12024
13198
|
{
|
|
12025
13199
|
"binaryResponse": false,
|
|
12026
13200
|
"bodyRequired": false,
|
|
@@ -14705,6 +15879,76 @@ function canonicalizeCliReferences(description) {
|
|
|
14705
15879
|
return description.replaceAll("`primitive emails:latest`", "`primitive emails latest`").replaceAll("`primitive describe emails:get-email | jq '.responseSchema.properties'`", "`primitive describe emails:get | jq '.responseSchema.properties'`");
|
|
14706
15880
|
}
|
|
14707
15881
|
//#endregion
|
|
15882
|
+
//#region src/oclif/commands/agent-upgrade.ts
|
|
15883
|
+
/**
|
|
15884
|
+
* Interactive upgrade of an emailless agent account to a full developer
|
|
15885
|
+
* account: starts the email claim, prompts for the emailed code, and verifies
|
|
15886
|
+
* it. Combines the generated `agent:claim` (start) and `agent:claim-verify`
|
|
15887
|
+
* into one flow with a prompt, mirroring the `signup` interactive command.
|
|
15888
|
+
* Authenticated by the agent's own API key (the org is taken from the key).
|
|
15889
|
+
*/
|
|
15890
|
+
var AgentUpgradeCommand = class AgentUpgradeCommand extends Command {
|
|
15891
|
+
static description = "Upgrade an emailless agent account to a full developer account by confirming an email. Authenticated by the agent's own API key (PRIMITIVE_API_KEY).";
|
|
15892
|
+
static summary = "Upgrade an agent account to developer (email confirmation)";
|
|
15893
|
+
static examples = ["<%= config.bin %> agent upgrade --email you@example.com"];
|
|
15894
|
+
static flags = {
|
|
15895
|
+
email: Flags.string({ description: "Email to confirm. Prompted if omitted." }),
|
|
15896
|
+
code: Flags.string({ description: "Verification code from the email. Prompted if omitted." }),
|
|
15897
|
+
"api-key": Flags.string({
|
|
15898
|
+
env: "PRIMITIVE_API_KEY",
|
|
15899
|
+
description: "Agent API key (defaults to PRIMITIVE_API_KEY or saved credentials)."
|
|
15900
|
+
}),
|
|
15901
|
+
"api-base-url": Flags.string({ description: "Override the API base URL." })
|
|
15902
|
+
};
|
|
15903
|
+
async run() {
|
|
15904
|
+
const { flags } = await this.parse(AgentUpgradeCommand);
|
|
15905
|
+
const { apiClient } = await createAuthenticatedCliApiClient({
|
|
15906
|
+
apiKey: flags["api-key"],
|
|
15907
|
+
apiBaseUrl: flags["api-base-url"],
|
|
15908
|
+
configDir: this.config.configDir
|
|
15909
|
+
});
|
|
15910
|
+
const email = flags.email ?? await promptRequired$1("Email to confirm: ");
|
|
15911
|
+
const started = await startAgentClaim({
|
|
15912
|
+
body: { email },
|
|
15913
|
+
client: apiClient.client,
|
|
15914
|
+
responseStyle: "fields"
|
|
15915
|
+
});
|
|
15916
|
+
if (!started.data) {
|
|
15917
|
+
writeErrorWithHints(extractErrorPayload(started.error));
|
|
15918
|
+
this.exit(1);
|
|
15919
|
+
return;
|
|
15920
|
+
}
|
|
15921
|
+
process$1.stderr.write(`Verification code sent to ${email}.\n`);
|
|
15922
|
+
const verified = await verifyAgentClaim({
|
|
15923
|
+
body: { verification_code: flags.code ?? await promptRequired$1("Verification code: ") },
|
|
15924
|
+
client: apiClient.client,
|
|
15925
|
+
responseStyle: "fields"
|
|
15926
|
+
});
|
|
15927
|
+
const result = verified.data?.data;
|
|
15928
|
+
if (result) {
|
|
15929
|
+
this.log(JSON.stringify(result, null, 2));
|
|
15930
|
+
process$1.stderr.write(`Upgraded to ${result.plan}. Your API key and managed inbox carry over; the send cap is lifted.\n`);
|
|
15931
|
+
return;
|
|
15932
|
+
}
|
|
15933
|
+
writeErrorWithHints(extractErrorPayload(verified.error));
|
|
15934
|
+
this.exit(1);
|
|
15935
|
+
}
|
|
15936
|
+
};
|
|
15937
|
+
async function promptRequired$1(question) {
|
|
15938
|
+
const rl = createInterface({
|
|
15939
|
+
input: process$1.stdin,
|
|
15940
|
+
output: process$1.stderr
|
|
15941
|
+
});
|
|
15942
|
+
try {
|
|
15943
|
+
for (;;) {
|
|
15944
|
+
const answer = (await rl.question(question)).trim();
|
|
15945
|
+
if (answer) return answer;
|
|
15946
|
+
}
|
|
15947
|
+
} finally {
|
|
15948
|
+
rl.close();
|
|
15949
|
+
}
|
|
15950
|
+
}
|
|
15951
|
+
//#endregion
|
|
14708
15952
|
//#region src/oclif/attachments.ts
|
|
14709
15953
|
function readAttachmentBytes(path, readFile) {
|
|
14710
15954
|
try {
|
|
@@ -18138,8 +19382,8 @@ const PRIMITIVE_TEAM_AUTHOR = {
|
|
|
18138
19382
|
name: "Primitive Team",
|
|
18139
19383
|
url: "https://primitive.dev"
|
|
18140
19384
|
};
|
|
18141
|
-
const SDK_VERSION_RANGE = "^1.
|
|
18142
|
-
const CLI_VERSION_RANGE = "^1.
|
|
19385
|
+
const SDK_VERSION_RANGE = "^1.5.0";
|
|
19386
|
+
const CLI_VERSION_RANGE = "^1.5.0";
|
|
18143
19387
|
const ESBUILD_VERSION_RANGE = "^0.27.0";
|
|
18144
19388
|
function renderHandler() {
|
|
18145
19389
|
return `// env.PRIMITIVE_API_KEY, env.PRIMITIVE_WEBHOOK_SECRET, and
|
|
@@ -21284,6 +22528,251 @@ var LogoutCommand = class LogoutCommand extends Command {
|
|
|
21284
22528
|
}
|
|
21285
22529
|
};
|
|
21286
22530
|
//#endregion
|
|
22531
|
+
//#region src/oclif/commands/org-secrets-shared.ts
|
|
22532
|
+
function orgSecretsUrl(baseUrl, key) {
|
|
22533
|
+
const base = `${baseUrl.replace(/\/$/, "")}/org/secrets`;
|
|
22534
|
+
return key ? `${base}/${encodeURIComponent(key)}` : base;
|
|
22535
|
+
}
|
|
22536
|
+
function orgSecretsAuthHeaders(requestHeaders, apiKey) {
|
|
22537
|
+
return {
|
|
22538
|
+
...requestHeaders ?? {},
|
|
22539
|
+
...apiKey ? { authorization: `Bearer ${apiKey}` } : {}
|
|
22540
|
+
};
|
|
22541
|
+
}
|
|
22542
|
+
async function orgSecretsErrorPayload(response) {
|
|
22543
|
+
if ((response.headers.get("content-type")?.toLowerCase() ?? "").includes("application/json")) return response.json().catch(() => ({
|
|
22544
|
+
code: "http_error",
|
|
22545
|
+
message: `HTTP ${response.status} ${response.statusText}`.trim()
|
|
22546
|
+
}));
|
|
22547
|
+
return {
|
|
22548
|
+
code: "http_error",
|
|
22549
|
+
message: (await response.text().catch(() => "")).trim() || `HTTP ${response.status} ${response.statusText}`.trim()
|
|
22550
|
+
};
|
|
22551
|
+
}
|
|
22552
|
+
async function runOrgSecretsRequest(fetchImpl, baseUrl, headers, op) {
|
|
22553
|
+
const url = op.kind === "remove" ? orgSecretsUrl(baseUrl, op.key) : orgSecretsUrl(baseUrl);
|
|
22554
|
+
const init = op.kind === "set" ? {
|
|
22555
|
+
method: "POST",
|
|
22556
|
+
headers: {
|
|
22557
|
+
...headers,
|
|
22558
|
+
"content-type": "application/json"
|
|
22559
|
+
},
|
|
22560
|
+
body: JSON.stringify({
|
|
22561
|
+
key: op.key,
|
|
22562
|
+
value: op.value
|
|
22563
|
+
})
|
|
22564
|
+
} : op.kind === "remove" ? {
|
|
22565
|
+
method: "DELETE",
|
|
22566
|
+
headers
|
|
22567
|
+
} : { headers };
|
|
22568
|
+
let response;
|
|
22569
|
+
try {
|
|
22570
|
+
response = await fetchImpl(url, init);
|
|
22571
|
+
} catch (error) {
|
|
22572
|
+
return {
|
|
22573
|
+
kind: "error",
|
|
22574
|
+
payload: extractErrorPayload(error)
|
|
22575
|
+
};
|
|
22576
|
+
}
|
|
22577
|
+
if (!response.ok) return {
|
|
22578
|
+
kind: "error",
|
|
22579
|
+
payload: extractErrorPayload(await orgSecretsErrorPayload(response))
|
|
22580
|
+
};
|
|
22581
|
+
if (op.kind === "remove") return {
|
|
22582
|
+
kind: "ok",
|
|
22583
|
+
data: null
|
|
22584
|
+
};
|
|
22585
|
+
const body = await response.json().catch(() => ({}));
|
|
22586
|
+
if (op.kind === "list") return {
|
|
22587
|
+
kind: "ok",
|
|
22588
|
+
data: body.data?.items ?? []
|
|
22589
|
+
};
|
|
22590
|
+
return {
|
|
22591
|
+
kind: "ok",
|
|
22592
|
+
data: body.data ?? {}
|
|
22593
|
+
};
|
|
22594
|
+
}
|
|
22595
|
+
//#endregion
|
|
22596
|
+
//#region src/oclif/commands/org-secrets-list.ts
|
|
22597
|
+
var OrgSecretsListCommand = class OrgSecretsListCommand extends Command {
|
|
22598
|
+
static description = `List your organization's global secrets.
|
|
22599
|
+
|
|
22600
|
+
Global secrets apply to every function in the org and are read as
|
|
22601
|
+
\`env.<KEY>\` in handlers. Only the keys and timestamps are returned;
|
|
22602
|
+
the values are encrypted at rest and never surfaced.`;
|
|
22603
|
+
static summary = "List global secrets (keys only; values never returned)";
|
|
22604
|
+
static examples = ["<%= config.bin %> org secrets list"];
|
|
22605
|
+
static flags = {
|
|
22606
|
+
"api-key": Flags.string({
|
|
22607
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
22608
|
+
env: "PRIMITIVE_API_KEY"
|
|
22609
|
+
}),
|
|
22610
|
+
"api-base-url": Flags.string({
|
|
22611
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
22612
|
+
env: "PRIMITIVE_API_BASE_URL",
|
|
22613
|
+
hidden: true
|
|
22614
|
+
}),
|
|
22615
|
+
time: Flags.boolean({ description: TIME_FLAG_DESCRIPTION })
|
|
22616
|
+
};
|
|
22617
|
+
async run() {
|
|
22618
|
+
const { flags } = await this.parse(OrgSecretsListCommand);
|
|
22619
|
+
await runWithTiming(flags.time, async () => {
|
|
22620
|
+
const { auth, baseUrlOverridden, requestConfig } = await createAuthenticatedCliApiClient({
|
|
22621
|
+
apiKey: flags["api-key"],
|
|
22622
|
+
apiBaseUrl: flags["api-base-url"],
|
|
22623
|
+
configDir: this.config.configDir
|
|
22624
|
+
});
|
|
22625
|
+
const outcome = await runOrgSecretsRequest(fetch, requestConfig.resolvedApiBaseUrl, orgSecretsAuthHeaders(requestConfig.headers, auth.apiKey), { kind: "list" });
|
|
22626
|
+
if (outcome.kind === "error") {
|
|
22627
|
+
writeErrorWithHints(outcome.payload);
|
|
22628
|
+
surfaceUnauthorizedHint({
|
|
22629
|
+
auth,
|
|
22630
|
+
baseUrlOverridden,
|
|
22631
|
+
configDir: this.config.configDir,
|
|
22632
|
+
payload: outcome.payload
|
|
22633
|
+
});
|
|
22634
|
+
process.exitCode = 1;
|
|
22635
|
+
return;
|
|
22636
|
+
}
|
|
22637
|
+
this.log(JSON.stringify(outcome.data, null, 2));
|
|
22638
|
+
});
|
|
22639
|
+
}
|
|
22640
|
+
};
|
|
22641
|
+
//#endregion
|
|
22642
|
+
//#region src/oclif/commands/org-secrets-remove.ts
|
|
22643
|
+
var OrgSecretsRemoveCommand = class OrgSecretsRemoveCommand extends Command {
|
|
22644
|
+
static description = `Delete a global secret.
|
|
22645
|
+
|
|
22646
|
+
Deployed functions keep the previous value until each is redeployed. A
|
|
22647
|
+
function that defines its own secret of the same name is unaffected.`;
|
|
22648
|
+
static summary = "Delete a global secret";
|
|
22649
|
+
static aliases = ["org:secrets:delete"];
|
|
22650
|
+
static examples = ["<%= config.bin %> org secrets remove --key STRIPE_KEY"];
|
|
22651
|
+
static flags = {
|
|
22652
|
+
"api-key": Flags.string({
|
|
22653
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
22654
|
+
env: "PRIMITIVE_API_KEY"
|
|
22655
|
+
}),
|
|
22656
|
+
"api-base-url": Flags.string({
|
|
22657
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
22658
|
+
env: "PRIMITIVE_API_BASE_URL",
|
|
22659
|
+
hidden: true
|
|
22660
|
+
}),
|
|
22661
|
+
key: Flags.string({
|
|
22662
|
+
description: "Global secret key to delete.",
|
|
22663
|
+
required: true
|
|
22664
|
+
}),
|
|
22665
|
+
time: Flags.boolean({ description: TIME_FLAG_DESCRIPTION })
|
|
22666
|
+
};
|
|
22667
|
+
async run() {
|
|
22668
|
+
const { flags } = await this.parse(OrgSecretsRemoveCommand);
|
|
22669
|
+
await runWithTiming(flags.time, async () => {
|
|
22670
|
+
const { auth, baseUrlOverridden, requestConfig } = await createAuthenticatedCliApiClient({
|
|
22671
|
+
apiKey: flags["api-key"],
|
|
22672
|
+
apiBaseUrl: flags["api-base-url"],
|
|
22673
|
+
configDir: this.config.configDir
|
|
22674
|
+
});
|
|
22675
|
+
const outcome = await runOrgSecretsRequest(fetch, requestConfig.resolvedApiBaseUrl, orgSecretsAuthHeaders(requestConfig.headers, auth.apiKey), {
|
|
22676
|
+
kind: "remove",
|
|
22677
|
+
key: flags.key
|
|
22678
|
+
});
|
|
22679
|
+
if (outcome.kind === "error") {
|
|
22680
|
+
writeErrorWithHints(outcome.payload);
|
|
22681
|
+
surfaceUnauthorizedHint({
|
|
22682
|
+
auth,
|
|
22683
|
+
baseUrlOverridden,
|
|
22684
|
+
configDir: this.config.configDir,
|
|
22685
|
+
payload: outcome.payload
|
|
22686
|
+
});
|
|
22687
|
+
process.exitCode = 1;
|
|
22688
|
+
return;
|
|
22689
|
+
}
|
|
22690
|
+
process.stderr.write(`Global secret ${flags.key} deleted. Deployed functions keep the previous value until each is redeployed.\n`);
|
|
22691
|
+
});
|
|
22692
|
+
}
|
|
22693
|
+
};
|
|
22694
|
+
//#endregion
|
|
22695
|
+
//#region src/oclif/commands/org-secrets-set.ts
|
|
22696
|
+
var OrgSecretsSetCommand = class OrgSecretsSetCommand extends Command {
|
|
22697
|
+
static description = `Set a global secret available to every function as \`env.<KEY>\`.
|
|
22698
|
+
|
|
22699
|
+
Global secrets are read into each function at deploy time, so a new or
|
|
22700
|
+
changed value lands in a function only on its next redeploy. A function
|
|
22701
|
+
secret with the same key overrides the global value for that function.
|
|
22702
|
+
|
|
22703
|
+
Keys must match \`^[A-Z_][A-Z0-9_]*$\` (uppercase letters, digits,
|
|
22704
|
+
underscores; first character a letter or underscore). System-managed keys
|
|
22705
|
+
are reserved and rejected. ${SINGLE_SECRET_VALUE_SOURCE_DESCRIPTION}`;
|
|
22706
|
+
static summary = "Set a global secret shared across all functions";
|
|
22707
|
+
static examples = [
|
|
22708
|
+
"<%= config.bin %> org secrets set --key STRIPE_KEY --value sk_live_...",
|
|
22709
|
+
"<%= config.bin %> org secrets set --key OPENAI_KEY --value-from-env OPENAI_KEY",
|
|
22710
|
+
"printf '%s' \"$OPENAI_KEY\" | <%= config.bin %> org secrets set --key OPENAI_KEY --stdin"
|
|
22711
|
+
];
|
|
22712
|
+
static flags = {
|
|
22713
|
+
"api-key": Flags.string({
|
|
22714
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
22715
|
+
env: "PRIMITIVE_API_KEY"
|
|
22716
|
+
}),
|
|
22717
|
+
"api-base-url": Flags.string({
|
|
22718
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
22719
|
+
env: "PRIMITIVE_API_BASE_URL",
|
|
22720
|
+
hidden: true
|
|
22721
|
+
}),
|
|
22722
|
+
key: Flags.string({
|
|
22723
|
+
description: "Secret key. Uppercase letters, digits, underscores; must start with a letter or underscore. System-managed keys are reserved.",
|
|
22724
|
+
required: true
|
|
22725
|
+
}),
|
|
22726
|
+
value: Flags.string({ description: "Secret value (up to 4096 UTF-8 bytes). Encrypted at rest. Visible in shell history and process argv; prefer a non-argv source for sensitive values." }),
|
|
22727
|
+
"value-from-env": Flags.string({ description: "Environment variable to read as the secret value. Example: --value-from-env OPENAI_KEY reads process.env.OPENAI_KEY." }),
|
|
22728
|
+
"value-file": Flags.string({ description: "UTF-8 file to read as the secret value. The full file contents become the value." }),
|
|
22729
|
+
"value-from-env-file": Flags.string({ description: "Dotenv-style file to read as the secret value. Use FILE to read --key from that file, or FILE:KEY to read a different key." }),
|
|
22730
|
+
stdin: Flags.boolean({ description: "Read the secret value from stdin. A single trailing line ending is stripped." }),
|
|
22731
|
+
time: Flags.boolean({ description: TIME_FLAG_DESCRIPTION })
|
|
22732
|
+
};
|
|
22733
|
+
async run() {
|
|
22734
|
+
const { flags } = await this.parse(OrgSecretsSetCommand);
|
|
22735
|
+
await runWithTiming(flags.time, async () => {
|
|
22736
|
+
const { auth, baseUrlOverridden, requestConfig } = await createAuthenticatedCliApiClient({
|
|
22737
|
+
apiKey: flags["api-key"],
|
|
22738
|
+
apiBaseUrl: flags["api-base-url"],
|
|
22739
|
+
configDir: this.config.configDir
|
|
22740
|
+
});
|
|
22741
|
+
const resolved = resolveSingleSecretValue({
|
|
22742
|
+
key: flags.key,
|
|
22743
|
+
value: flags.value,
|
|
22744
|
+
valueFile: flags["value-file"],
|
|
22745
|
+
valueFromEnv: flags["value-from-env"],
|
|
22746
|
+
valueFromEnvFile: flags["value-from-env-file"],
|
|
22747
|
+
stdin: flags.stdin
|
|
22748
|
+
});
|
|
22749
|
+
if (resolved.kind === "error") {
|
|
22750
|
+
process.stderr.write(`${resolved.message}\n`);
|
|
22751
|
+
process.exitCode = 1;
|
|
22752
|
+
return;
|
|
22753
|
+
}
|
|
22754
|
+
const outcome = await runOrgSecretsRequest(fetch, requestConfig.resolvedApiBaseUrl, orgSecretsAuthHeaders(requestConfig.headers, auth.apiKey), {
|
|
22755
|
+
kind: "set",
|
|
22756
|
+
key: flags.key,
|
|
22757
|
+
value: resolved.value
|
|
22758
|
+
});
|
|
22759
|
+
if (outcome.kind === "error") {
|
|
22760
|
+
writeErrorWithHints(outcome.payload);
|
|
22761
|
+
surfaceUnauthorizedHint({
|
|
22762
|
+
auth,
|
|
22763
|
+
baseUrlOverridden,
|
|
22764
|
+
configDir: this.config.configDir,
|
|
22765
|
+
payload: outcome.payload
|
|
22766
|
+
});
|
|
22767
|
+
process.exitCode = 1;
|
|
22768
|
+
return;
|
|
22769
|
+
}
|
|
22770
|
+
this.log(JSON.stringify(outcome.data, null, 2));
|
|
22771
|
+
process.stderr.write(`Global secret ${flags.key} saved. Deployed functions pick it up on their next redeploy; a function secret of the same name overrides it.\n`);
|
|
22772
|
+
});
|
|
22773
|
+
}
|
|
22774
|
+
};
|
|
22775
|
+
//#endregion
|
|
21287
22776
|
//#region src/oclif/message-body-sources.ts
|
|
21288
22777
|
function defaultReadFile(path) {
|
|
21289
22778
|
return readFileSync(path, "utf8");
|
|
@@ -22657,6 +24146,10 @@ const CANONICAL_OPERATION_ALIASES = {
|
|
|
22657
24146
|
"account:show": "account:get-account",
|
|
22658
24147
|
"account:storage": "account:get-storage-stats",
|
|
22659
24148
|
"account:webhook-secret": "account:get-webhook-secret",
|
|
24149
|
+
"agent:claim": "agent:start-agent-claim",
|
|
24150
|
+
"agent:claim-link": "agent:create-agent-claim-link",
|
|
24151
|
+
"agent:claim-verify": "agent:verify-agent-claim",
|
|
24152
|
+
"agent:create": "agent:create-agent-account",
|
|
22660
24153
|
"deliveries:list": "webhook-deliveries:list-deliveries",
|
|
22661
24154
|
"deliveries:replay": "webhook-deliveries:replay-delivery",
|
|
22662
24155
|
"domains:add": "domains:add-domain",
|
|
@@ -22715,6 +24208,7 @@ const OVERRIDDEN_OPERATION_IDS = new Set([
|
|
|
22715
24208
|
const generatedCommands = Object.fromEntries(operationManifest.filter((operation) => !OVERRIDDEN_OPERATION_IDS.has(operationId(operation))).map((operation) => [operationId(operation), createOperationCommand(operation)]));
|
|
22716
24209
|
const COMMANDS = {
|
|
22717
24210
|
completion: CompletionCommand,
|
|
24211
|
+
"agent:upgrade": AgentUpgradeCommand,
|
|
22718
24212
|
"list-operations": ListOperationsCommand,
|
|
22719
24213
|
config: ConfigCommand,
|
|
22720
24214
|
"config:list": ConfigListCommand,
|
|
@@ -22767,6 +24261,9 @@ const COMMANDS = {
|
|
|
22767
24261
|
"functions:deploy": FunctionsDeployCommand,
|
|
22768
24262
|
"functions:redeploy": FunctionsRedeployCommand,
|
|
22769
24263
|
"functions:set-secret": FunctionsSetSecretCommand,
|
|
24264
|
+
"org:secrets:list": OrgSecretsListCommand,
|
|
24265
|
+
"org:secrets:set": OrgSecretsSetCommand,
|
|
24266
|
+
"org:secrets:remove": OrgSecretsRemoveCommand,
|
|
22770
24267
|
"functions:test": FunctionsTestFunctionCommand,
|
|
22771
24268
|
"functions:test-function": FunctionsTestFunctionCommand,
|
|
22772
24269
|
"functions:route-set": FunctionsRouteSetCommand,
|