a2a-exposed 0.7.31 → 0.7.33
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/lib/main.mjs +13 -13
- package/lib/pair.mjs +3 -3
- package/package.json +1 -1
- package/worker/src/index.ts +1 -1
- package/worker/src/pairing.ts +1 -1
- package/worker/src/version.ts +1 -1
- package/worker/test/hosted.test.ts +2 -1
package/lib/main.mjs
CHANGED
|
@@ -142,10 +142,10 @@ Pairing (OAuth 2.0 device flow, RFC 8628: agents connect without pasting tokens
|
|
|
142
142
|
pair set-password the same in a terminal, no echo (the human runs it; never via argv/stdin)
|
|
143
143
|
pair set-oidc --issuer URL --client-id ID --subjects SUB[,SUB...] [--methods password,oidc] [--secret-stdin]
|
|
144
144
|
optional OpenID Connect approval on /device and the MCP consent page. The client
|
|
145
|
-
secret is APPROVAL_OIDC_CLIENT_SECRET in the environment
|
|
146
|
-
--secret-stdin
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
secret deploy uploads is APPROVAL_OIDC_CLIENT_SECRET in the environment you use for
|
|
146
|
+
deploy. --secret-stdin checks one line and discards it, so export the variable
|
|
147
|
+
before deploy. config.env keeps the issuer and client id.
|
|
148
|
+
Leave the issuer unset and approval stays the password page
|
|
149
149
|
pair list [--json] pending pairing requests (code, claimed name/card, address), the approval mode and
|
|
150
150
|
when the approval password was set
|
|
151
151
|
pair approve <code> approve (only with --pairing-approval agent, after your human said yes)
|
|
@@ -186,20 +186,20 @@ Control plane account (only when that deployment's login is on)
|
|
|
186
186
|
After sign-in, /app shows the account and its agents. Each agent is listed
|
|
187
187
|
by its hostname. A hosted name opens
|
|
188
188
|
that agent's page: MCP connectors (revoke needs a recent sign-in), a
|
|
189
|
-
message log
|
|
190
|
-
|
|
191
|
-
token shows its code. An empty outbound list
|
|
192
|
-
|
|
189
|
+
message log of recent history. Opening this log leaves a pending wake in place until you list the inbox. The SQL download
|
|
190
|
+
is a redacted copy and replaces a pasted owner token. Peer times are labeled UTC. A pairing
|
|
191
|
+
token shows its code. An empty outbound list says peers added with the CLI
|
|
192
|
+
on your machine stay in that CLI. Sign out is on that
|
|
193
193
|
page. Creating an agent shows the owner token once. The agent page rotates
|
|
194
194
|
that token after a confirmation and a recent sign-in. The new token is
|
|
195
195
|
shown once on that agent's page. The previous one stops working immediately.
|
|
196
196
|
The token is shown only when the stored hash is still that token. A Copy button sits next to it. Without JavaScript the value still copies.
|
|
197
|
-
Deleting an agent asks for its name and a recent sign-in. The account page says how many slots remain. A self-hosted inbox has no such delete.
|
|
197
|
+
Deleting an agent asks for its name and a recent sign-in. The account page says how many hosted slots remain. A self-hosted inbox has no such delete.
|
|
198
198
|
That page is not stored.
|
|
199
|
-
FREE_AGENT_LIMIT=2 caps a free account at 2 hosted agents.
|
|
200
|
-
Unset, there is no limit. The database rejects another insert.
|
|
199
|
+
FREE_AGENT_LIMIT=2 caps a free account at 2 hosted agents. A Cloudflare agent stays outside that count. An account's own limit overrides it.
|
|
200
|
+
Unset, there is no limit. The database rejects another hosted insert.
|
|
201
201
|
SIGNUP_ALLOWLIST, when set, admits only those verified emails. Unset, sign-in stays open.
|
|
202
|
-
|
|
202
|
+
Sign-in uses GitHub, Google, or email. Connect Cloudflare from the account page after you sign in.
|
|
203
203
|
A refusal returns to /app?error=invite and the page says Sign-in is invite-only for now.
|
|
204
204
|
The control Worker logs social_sign_in_failed before the
|
|
205
205
|
provider page, social_sign_in_timeout when that sign-in does not
|
|
@@ -269,7 +269,7 @@ export async function main(argv) {
|
|
|
269
269
|
if (name === "--version" || name === "-v") return console.log(VERSION);
|
|
270
270
|
if (rest.includes("--help") || rest.includes("-h")) return console.log(HELP);
|
|
271
271
|
if (name === "pair" && rest[0] === "set-oidc" && rest.some((a) => /^--(secret|client-secret)(=|$)/.test(a)))
|
|
272
|
-
throw new CliError("
|
|
272
|
+
throw new CliError("export APPROVAL_OIDC_CLIENT_SECRET or pass --secret-stdin. --secret-stdin checks the line and discards it. Deploy uploads only the environment variable");
|
|
273
273
|
if (name === "pair" && rest[0] === "set-password") {
|
|
274
274
|
// only --web [--ttl M] [--json]: the password itself never comes from argv, stdin or the environment
|
|
275
275
|
const extra = rest.slice(1);
|
package/lib/pair.mjs
CHANGED
|
@@ -120,7 +120,7 @@ export async function setOidc(o, extra = []) {
|
|
|
120
120
|
}
|
|
121
121
|
let sawStdin = false;
|
|
122
122
|
if (o["secret-stdin"]) {
|
|
123
|
-
if (process.stdin.isTTY) die("--secret-stdin reads the client secret from a pipe. Or export APPROVAL_OIDC_CLIENT_SECRET.
|
|
123
|
+
if (process.stdin.isTTY) die("--secret-stdin reads the client secret from a pipe. Or export APPROVAL_OIDC_CLIENT_SECRET. --secret-stdin checks the line and discards it. Deploy uploads only the environment variable");
|
|
124
124
|
const chunks = [];
|
|
125
125
|
for await (const c of process.stdin) chunks.push(c);
|
|
126
126
|
const secret = Buffer.concat(chunks).toString("utf8").replace(/\r?\n$/, "");
|
|
@@ -129,7 +129,7 @@ export async function setOidc(o, extra = []) {
|
|
|
129
129
|
const fromEnv = process.env.APPROVAL_OIDC_CLIENT_SECRET || "";
|
|
130
130
|
if (fromEnv && fromEnv !== secret) console.error("The secret on stdin differs from APPROVAL_OIDC_CLIENT_SECRET. Deploy uploads the environment variable. Neither value was printed or saved.");
|
|
131
131
|
} else if (!(process.env.APPROVAL_OIDC_CLIENT_SECRET || "").trim()) {
|
|
132
|
-
die("export APPROVAL_OIDC_CLIENT_SECRET or pass --secret-stdin.
|
|
132
|
+
die("export APPROVAL_OIDC_CLIENT_SECRET or pass --secret-stdin. --secret-stdin checks the line and discards it. Deploy uploads only the environment variable");
|
|
133
133
|
}
|
|
134
134
|
C.saveConfig({
|
|
135
135
|
APPROVAL_OIDC_ISSUER: String(o.issuer).trim(),
|
|
@@ -141,7 +141,7 @@ export async function setOidc(o, extra = []) {
|
|
|
141
141
|
console.error("The client secret was not written there and was not printed.");
|
|
142
142
|
if (sawStdin && !(process.env.APPROVAL_OIDC_CLIENT_SECRET || "").trim())
|
|
143
143
|
console.error(`Export APPROVAL_OIDC_CLIENT_SECRET in the environment you use for deploy. This command did not store it.`);
|
|
144
|
-
console.error(`The next \`npx -y a2a-exposed@latest deploy\` uploads APPROVAL_OIDC_CLIENT_SECRET
|
|
144
|
+
console.error(`The next \`npx -y a2a-exposed@latest deploy\` uploads APPROVAL_OIDC_CLIENT_SECRET only when that variable is set in the environment. A line from --secret-stdin is discarded.`);
|
|
145
145
|
console.error("Password approval stays available unless --methods oidc (and only once the issuer, client id, secret and allowlist are all set).");
|
|
146
146
|
}
|
|
147
147
|
|
package/package.json
CHANGED
package/worker/src/index.ts
CHANGED
|
@@ -2233,7 +2233,7 @@ export async function runOwnerRpc(ctx: TenantContext, ectx: ExecutionContext, in
|
|
|
2233
2233
|
data = matched.route.search === "?format=sql"
|
|
2234
2234
|
? {
|
|
2235
2235
|
exportedAt: file.exportedAt,
|
|
2236
|
-
sql: "--
|
|
2236
|
+
sql: "-- Redacted dashboard copy for reading. The full dump is npx a2a-exposed export with the owner token.\n"
|
|
2237
2237
|
+ "-- Stored token hashes are replaced with redacted: values that do not authenticate, or left out. Ciphertext, push tokens, re-pair hashes, OAuth codes, the approval-password hash, password-setup hashes, and OpenID Connect sign-in rows are omitted.\n"
|
|
2238
2238
|
+ toSql(file, { skip: REDACTED_SQL_SKIP }),
|
|
2239
2239
|
}
|
package/worker/src/pairing.ts
CHANGED
|
@@ -254,7 +254,7 @@ export function landingPage(m: LandingModel, nonce: string): string {
|
|
|
254
254
|
? `<h2>Connect your agent</h2><p>Agents get a bearer token through the OAuth device flow: your agent asks, and this agent's owner approves the request on the <a href="/device">pairing page</a>. No secrets go through chat. With the a2a-exposed CLI, your agent runs:</p><p><code>${DEFAULT_CLI} connect ${esc(m.base)}</code></p>`
|
|
255
255
|
: `<h2>Connect your agent</h2><p>Pairing is turned off here: ask this agent's operator for a bearer token.</p>`;
|
|
256
256
|
return pageShell(m.name, nonce, `${desc}
|
|
257
|
-
<p class="n info">This is an <a href="https://a2a-protocol.org/">A2A (Agent2Agent)</a> endpoint
|
|
257
|
+
<p class="n info">This is an <a href="https://a2a-protocol.org/">A2A (Agent2Agent)</a> endpoint for agents.${m.proxy ? "" : " Messages land in its owner's inbox, which wakes the agent."}</p>
|
|
258
258
|
<table>
|
|
259
259
|
<tr><th>Agent card</th><td><a href="/.well-known/agent-card.json">${esc(card)}</a></td></tr>
|
|
260
260
|
<tr><th>JSON-RPC endpoint</th><td><code>POST ${esc(m.base)}/</code></td></tr>
|
package/worker/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Inbox build. Keep this equal to `version` in cli/package.json. */
|
|
2
|
-
export const VERSION = "0.7.
|
|
2
|
+
export const VERSION = "0.7.33";
|
|
@@ -627,7 +627,8 @@ test("TenantStore.owner runs an allowlisted owner call and does not return a pee
|
|
|
627
627
|
const sql = (sqlDump.body as { sql?: string }).sql ?? "";
|
|
628
628
|
assert.match(sql, /note \[redacted\] end/);
|
|
629
629
|
assert.match(sql, /redacted:ada/);
|
|
630
|
-
assert.match(sql, /
|
|
630
|
+
assert.match(sql, /Redacted dashboard copy for reading/);
|
|
631
|
+
assert.equal(sql.includes("not a backup"), false);
|
|
631
632
|
assert.equal(sql.includes(pasted), false);
|
|
632
633
|
assert.equal(sql.includes("oauth_codes"), false);
|
|
633
634
|
assert.equal(sql.includes("oidc_txns"), false);
|