run402 3.2.0 → 3.3.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/lib/transfer.mjs CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  positionalArgs,
11
11
  } from "./argparse.mjs";
12
12
 
13
- const HELP = `run402 transfer — Two-party project transfer (v1.59)
13
+ const HELP = `run402 transfer — Project transfer, one noun for both recipient kinds (v1.93+)
14
14
 
15
15
  Usage:
16
16
  run402 transfer init --to <wallet|email> [--project <id>] [--billing-policy migrate] [--message <text>] [--kysigned <record_id>] [--retain-collaborator developer]
@@ -18,22 +18,22 @@ Usage:
18
18
  run402 transfer list [--incoming | --outgoing] [--limit N] [--offset N]
19
19
  run402 transfer accept <transfer_id>
20
20
  run402 transfer claim <transfer_id> [--into <organization_id>] [--accept-retained-collaborator]
21
- run402 transfer cancel <transfer_id> [--reason <text>] [--handoff]
21
+ run402 transfer cancel <transfer_id> [--reason <text>]
22
22
 
23
23
  Subcommands:
24
- init Initiate ownership change. --to <wallet> = two-party wallet transfer;
25
- --to <email> = email->org handoff (the recipient claims it).
26
- preview Fetch the safe review document (add --handoff for an email handoff)
27
- list List pending transfers (incoming default, --outgoing, or --handoffs)
28
- accept Accept an incoming wallet transfer (your wallet must be the to_wallet)
29
- claim Claim an incoming email handoff into an org (--into <id>; omit = new org)
30
- cancel Cancel a pending transfer/handoff (--handoff routes to a handoff)
24
+ init Initiate ownership change. --to <wallet> = two-party wallet transfer
25
+ (completed by 'accept'); --to <email> = email->org transfer (completed by 'claim').
26
+ preview Fetch the safe review document (wallet or email kind-agnostic)
27
+ list List pending transfers (incoming default, or --outgoing) — both kinds, unioned
28
+ accept Accept an incoming WALLET transfer (your wallet must be the to_wallet)
29
+ claim Claim an incoming EMAIL transfer into an org (--into <id>; omit = new org)
30
+ cancel Cancel a pending transfer of either kind
31
31
 
32
32
  Notes:
33
33
  - Owner-side mutations on a project with a pending transfer return 409
34
34
  PROJECT_HAS_PENDING_TRANSFER. Cancel the transfer or wait 72h for expiry.
35
35
  - Phase 1A supports only billing_policy=migrate (default).
36
- - Secret VALUES are inherited by the recipient on accept; rotation is advised.
36
+ - Secret VALUES are inherited by the recipient on completion; rotation is advised.
37
37
  - GitHub repo ownership is NOT transferred — handle that out of band.
38
38
  `;
39
39
 
@@ -45,17 +45,18 @@ Usage:
45
45
 
46
46
  Options:
47
47
  --project <id> Project id (defaults to the active project)
48
- --to <wallet> Recipient wallet (required). Any case; lowercased server-side.
49
- --billing-policy <p> Billing policy. Phase 1A only allows 'migrate' (default).
48
+ --to <wallet|email> Recipient (required). A wallet uses the two-party rail (completed by
49
+ 'accept'); an email uses the email->org rail (completed by 'claim').
50
+ --billing-policy <p> Billing policy (wallet rail). Phase 1A only allows 'migrate' (default).
50
51
  --message <text> Optional note shown to the recipient in preview + emails.
51
- --kysigned <record_id> Optional KySigned record id (Phase 1A: informational only).
52
- --retain-collaborator <role> Email handoffs only (v1.91): keep a 'developer' membership in
53
- the recipient's org after handoff. The recipient must accept it at
52
+ --kysigned <record_id> Optional KySigned record id (wallet rail; Phase 1A: informational only).
53
+ --retain-collaborator <role> Email recipients only (v1.91): keep a 'developer' membership in
54
+ the recipient's org after the transfer. The recipient must accept it at
54
55
  claim (--accept-retained-collaborator); omit for full severance.
55
56
 
56
57
  Notes:
57
- - Caller's wallet must currently own the project (gateway re-checks fresh DB).
58
- - Owner-side mutations on the project are frozen until accept/cancel/expiry.
58
+ - Caller's wallet/session must currently own or admin the project (gateway re-checks fresh DB).
59
+ - Owner-side mutations on the project are frozen until accept/claim/cancel/expiry.
59
60
  - The project lease stays with your organization; it is NOT refunded.
60
61
  `,
61
62
  preview: `run402 transfer preview — Fetch the preview document
@@ -64,21 +65,25 @@ Usage:
64
65
  run402 transfer preview <transfer_id>
65
66
 
66
67
  Returns project name, custom domains, subdomains, function names, secret NAMES
67
- (values are never returned), CI bindings that will be revoked on accept, and
68
- billing implications. Either the from_wallet or the to_wallet may preview.
68
+ (values are never returned), CI bindings that will be revoked on completion, and
69
+ billing implications. Works for both wallet- and email-addressed transfers; any
70
+ party to the transfer may preview.
69
71
  `,
70
72
  list: `run402 transfer list — List pending transfers
71
73
 
72
74
  Usage:
73
75
  run402 transfer list [--incoming | --outgoing] [--limit N] [--offset N]
74
76
 
77
+ Lists both wallet- and email-addressed transfers, unioned; each row carries
78
+ recipient_kind.
79
+
75
80
  Options:
76
- --incoming List transfers OFFERED TO your wallet (default).
77
- --outgoing List transfers INITIATED BY your wallet.
81
+ --incoming List transfers OFFERED TO you (default).
82
+ --outgoing List transfers INITIATED BY you.
78
83
  --limit N Page size (default 50).
79
84
  --offset N Pagination offset (default 0).
80
85
  `,
81
- accept: `run402 transfer accept — Accept an incoming transfer
86
+ accept: `run402 transfer accept — Accept an incoming WALLET transfer
82
87
 
83
88
  Usage:
84
89
  run402 transfer accept <transfer_id>
@@ -86,24 +91,26 @@ Usage:
86
91
  Your wallet must equal the transfer's to_wallet. The accept transaction
87
92
  atomically: flips ownership, revokes the previous owner's CI bindings on the
88
93
  project, enqueues notifications to both parties, and stamps a
89
- 'secrets_rotation_advised' advisory on the project.
94
+ 'secrets_rotation_advised' advisory on the project. (Email transfers complete
95
+ via 'claim', not 'accept'.)
90
96
  `,
91
97
  cancel: `run402 transfer cancel — Cancel a pending transfer
92
98
 
93
99
  Usage:
94
- run402 transfer cancel <transfer_id> [--reason <text>] [--handoff]
100
+ run402 transfer cancel <transfer_id> [--reason <text>]
95
101
 
96
- Either the from_wallet or the to_wallet may cancel. Already-processed
97
- transfers return 409 TRANSFER_ALREADY_PROCESSED. Pass --handoff to cancel an
98
- email->org handoff instead of a wallet transfer.
102
+ Cancels a pending transfer of either kind. You must be authorized for the row's
103
+ kind (a wallet signing party, or an owner/admin of the offering org / the
104
+ addressed-email principal). Already-processed transfers return 409
105
+ TRANSFER_ALREADY_PROCESSED.
99
106
  `,
100
- claim: `run402 transfer claim — Claim an incoming email handoff
107
+ claim: `run402 transfer claim — Claim an incoming EMAIL transfer
101
108
 
102
109
  Usage:
103
110
  run402 transfer claim <transfer_id> [--into <organization_id>] [--accept-retained-collaborator]
104
111
 
105
- Claims a handoff addressed to your email into an org you own. Omit --into to
106
- claim into a brand-new org. This is the email-handoff analog of 'accept'.
112
+ Claims an email-addressed transfer into an org you own. Omit --into to claim into
113
+ a brand-new org. This is the email analog of 'accept'.
107
114
 
108
115
  Options:
109
116
  --into <organization_id> Org to claim into (omit = brand-new org).
@@ -123,9 +130,9 @@ async function init(args) {
123
130
  if (extra.length > 0) {
124
131
  fail({ code: "BAD_USAGE", message: `Unexpected argument for transfer init: ${extra[0]}` });
125
132
  }
126
- const toWallet = flagValue(parsedArgs, "--to");
127
- if (!toWallet) {
128
- fail({ code: "BAD_USAGE", message: "Missing --to <wallet>" });
133
+ const to = flagValue(parsedArgs, "--to");
134
+ if (!to) {
135
+ fail({ code: "BAD_USAGE", message: "Missing --to <wallet|email>" });
129
136
  }
130
137
  const projectFlag = flagValue(parsedArgs, "--project");
131
138
  const projectId = await resolveProjectId(projectFlag);
@@ -144,17 +151,18 @@ async function init(args) {
144
151
  const kysigned = flagValue(parsedArgs, "--kysigned");
145
152
  const retainCollaborator = flagValue(parsedArgs, "--retain-collaborator");
146
153
 
147
- // One noun, two rails: an email recipient routes to the email->org handoff;
148
- // a wallet recipient routes to the two-party wallet transfer.
149
- const isEmail = toWallet.includes("@");
154
+ // One noun, two rails: an email recipient routes to the email->org completion
155
+ // ('claim'); a wallet recipient routes to the two-party wallet completion
156
+ // ('accept'). Both initiate on the SAME endpoint, discriminated by the body.
157
+ const isEmail = to.includes("@");
150
158
 
151
- // --retain-collaborator (v1.91) is a handoff-only opt-in: the sender keeps a
159
+ // --retain-collaborator (v1.91) is an email-only opt-in: the sender keeps a
152
160
  // developer membership in the recipient's org (recipient must accept at claim).
153
161
  if (retainCollaborator !== null) {
154
162
  if (!isEmail) {
155
163
  fail({
156
164
  code: "BAD_FLAG",
157
- message: "--retain-collaborator applies only to email handoffs; a wallet --to uses the two-party transfer rail.",
165
+ message: "--retain-collaborator applies only to email recipients; a wallet --to uses the two-party transfer rail.",
158
166
  details: { flag: "--retain-collaborator" },
159
167
  });
160
168
  }
@@ -167,21 +175,20 @@ async function init(args) {
167
175
  }
168
176
  }
169
177
 
170
- allowanceAuthHeaders(
171
- isEmail ? `/projects/v1/${projectId}/handoffs` : `/projects/v1/${projectId}/transfers`,
172
- );
178
+ // Both kinds initiate on the unified transfer endpoint — sign that path.
179
+ allowanceAuthHeaders(`/projects/v1/${projectId}/transfers`);
173
180
 
174
181
  try {
175
182
  const res = isEmail
176
- ? await getSdk().admin.transfers.initiateHandoff({
183
+ ? await getSdk().admin.transfers.initiate({
177
184
  projectId,
178
- toEmail: toWallet,
185
+ toEmail: to,
179
186
  message: message ?? undefined,
180
187
  retainCollaborator: retainCollaborator ? { role: retainCollaborator } : undefined,
181
188
  })
182
189
  : await getSdk().admin.transfers.initiate({
183
190
  projectId,
184
- toWallet,
191
+ toWallet: to,
185
192
  billingPolicy: billingPolicy ?? undefined,
186
193
  message: message ?? undefined,
187
194
  kysignedRecordId: kysigned ?? undefined,
@@ -194,19 +201,17 @@ async function init(args) {
194
201
 
195
202
  async function preview(args) {
196
203
  const parsedArgs = normalizeArgv(args);
197
- assertKnownFlags(parsedArgs, ["--handoff", "--help", "-h"]);
204
+ assertKnownFlags(parsedArgs, ["--help", "-h"]);
198
205
  const positionals = positionalArgs(parsedArgs);
199
206
  if (positionals.length !== 1) {
200
- fail({ code: "BAD_USAGE", message: "Usage: run402 transfer preview <transfer_id> [--handoff]" });
207
+ fail({ code: "BAD_USAGE", message: "Usage: run402 transfer preview <transfer_id>" });
201
208
  }
202
209
  const transferId = positionals[0];
203
- const handoff = parsedArgs.includes("--handoff");
204
- allowanceAuthHeaders(`/agent/v1/${handoff ? "handoffs" : "transfers"}/${transferId}`);
210
+ // Preview is kind-agnostic — one route serves wallet and email transfers.
211
+ allowanceAuthHeaders(`/agent/v1/transfers/${transferId}`);
205
212
 
206
213
  try {
207
- const data = handoff
208
- ? await getSdk().admin.transfers.previewHandoff(transferId)
209
- : await getSdk().admin.transfers.preview(transferId);
214
+ const data = await getSdk().admin.transfers.preview(transferId);
210
215
  console.log(JSON.stringify(data, null, 2));
211
216
  } catch (err) {
212
217
  reportSdkError(err);
@@ -216,24 +221,12 @@ async function preview(args) {
216
221
  async function list(args) {
217
222
  const parsedArgs = normalizeArgv(args);
218
223
  const valueFlags = ["--limit", "--offset"];
219
- assertKnownFlags(parsedArgs, [...valueFlags, "--incoming", "--outgoing", "--handoffs", "--help", "-h"], valueFlags);
224
+ assertKnownFlags(parsedArgs, [...valueFlags, "--incoming", "--outgoing", "--help", "-h"], valueFlags);
220
225
  const extra = positionalArgs(parsedArgs, valueFlags);
221
226
  if (extra.length > 0) {
222
227
  fail({ code: "BAD_USAGE", message: `Unexpected argument for transfer list: ${extra[0]}` });
223
228
  }
224
229
 
225
- // Email->org handoffs ride the same rail but have their own incoming inbox.
226
- if (parsedArgs.includes("--handoffs")) {
227
- allowanceAuthHeaders("/agent/v1/handoffs/incoming");
228
- try {
229
- const handoffs = await getSdk().admin.transfers.listIncomingHandoffs();
230
- console.log(JSON.stringify({ kind: "handoffs", handoffs }, null, 2));
231
- } catch (err) {
232
- reportSdkError(err);
233
- }
234
- return;
235
- }
236
-
237
230
  const incoming = parsedArgs.includes("--incoming");
238
231
  const outgoing = parsedArgs.includes("--outgoing");
239
232
  if (incoming && outgoing) {
@@ -252,6 +245,8 @@ async function list(args) {
252
245
  ? undefined
253
246
  : parseIntegerFlag("--offset", offsetFlag, { min: 0 });
254
247
 
248
+ // Incoming/outgoing are kind-agnostic — each returns the union of wallet- and
249
+ // email-addressed rows, tagged with recipient_kind.
255
250
  allowanceAuthHeaders(`/agent/v1/transfers/${direction}`);
256
251
 
257
252
  try {
@@ -286,20 +281,18 @@ async function accept(args) {
286
281
  async function cancel(args) {
287
282
  const parsedArgs = normalizeArgv(args);
288
283
  const valueFlags = ["--reason"];
289
- assertKnownFlags(parsedArgs, [...valueFlags, "--handoff", "--help", "-h"], valueFlags);
284
+ assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
290
285
  const positionals = positionalArgs(parsedArgs, valueFlags);
291
286
  if (positionals.length !== 1) {
292
- fail({ code: "BAD_USAGE", message: "Usage: run402 transfer cancel <transfer_id> [--reason <text>] [--handoff]" });
287
+ fail({ code: "BAD_USAGE", message: "Usage: run402 transfer cancel <transfer_id> [--reason <text>]" });
293
288
  }
294
289
  const transferId = positionals[0];
295
290
  const reason = flagValue(parsedArgs, "--reason");
296
- const handoff = parsedArgs.includes("--handoff");
297
- allowanceAuthHeaders(`/agent/v1/${handoff ? "handoffs" : "transfers"}/${transferId}/cancel`);
291
+ // Cancel is kind-agnostic — one route serves wallet and email transfers.
292
+ allowanceAuthHeaders(`/agent/v1/transfers/${transferId}/cancel`);
298
293
 
299
294
  try {
300
- const data = handoff
301
- ? await getSdk().admin.transfers.cancelHandoff(transferId)
302
- : await getSdk().admin.transfers.cancel(transferId, reason ?? undefined);
295
+ const data = await getSdk().admin.transfers.cancel(transferId, reason ?? undefined);
303
296
  console.log(JSON.stringify(data, null, 2));
304
297
  } catch (err) {
305
298
  reportSdkError(err);
@@ -319,10 +312,10 @@ async function claim(args) {
319
312
  // v1.91: accept the sender's retained-developer-membership offer (see the
320
313
  // preview's `retain_collaborator` block). Absent = full severance (default).
321
314
  const acceptRetain = parsedArgs.includes("--accept-retained-collaborator");
322
- allowanceAuthHeaders(`/agent/v1/handoffs/${transferId}/claim`);
315
+ allowanceAuthHeaders(`/agent/v1/transfers/${transferId}/claim`);
323
316
 
324
317
  try {
325
- const data = await getSdk().admin.transfers.claimHandoff(transferId, {
318
+ const data = await getSdk().admin.transfers.claim(transferId, {
326
319
  organizationId: into ?? undefined,
327
320
  acceptRetainedCollaborator: acceptRetain || undefined,
328
321
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "run402",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "CLI for Run402 — provision Postgres databases, deploy static sites, generate images, and manage wallets via x402 and MPP micropayments.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,36 +1,43 @@
1
1
  /**
2
- * `transfers` namespace — two-party SIWX-signed project transfer (v1.59).
2
+ * `transfers` namespace — the unified project-transfer noun (v1.93+).
3
3
  *
4
- * Exposed as `r.admin.transfers.*`. Phase 1A surface: initiate (owner-only),
5
- * preview, accept (recipient), cancel (either party), and incoming/outgoing
6
- * inboxes. The handoff is atomic at accept time: ownership flips, CI
7
- * bindings are revoked, secret names carry over (values are NOT visible to
8
- * the recipient before accept), and the project is decorated with a
9
- * persistent `secrets_rotation_advised` advisory.
4
+ * Exposed as `r.admin.transfers.*`. Project transfer is ONE capability,
5
+ * body-discriminated by recipient kind: a wallet recipient (`toWallet`, SIWX
6
+ * bilateral signing) or an email recipient (`toEmail`, the recipient claims
7
+ * into an org). Both ride the same `/transfers` surface there is no separate
8
+ * `/handoffs` noun (the gateway removed it in `unify-project-transfer-surface`).
10
9
  *
11
10
  * Gateway endpoints:
12
- * POST /projects/v1/:project_id/transfers — A initiates
13
- * GET /agent/v1/transfers/incoming — B's inbox
14
- * GET /agent/v1/transfers/outgoing — A's outbox
15
- * GET /agent/v1/transfers/:transfer_id — preview (either party)
16
- * POST /agent/v1/transfers/:transfer_id/accept — B accepts
17
- * POST /agent/v1/transfers/:transfer_id/cancel either party cancels
11
+ * POST /projects/v1/:project_id/transfers — initiate; body { to_wallet } XOR { to_email }
12
+ * GET /agent/v1/transfers/incoming — inbox (both kinds, unioned)
13
+ * GET /agent/v1/transfers/outgoing — outbox (both kinds, unioned)
14
+ * GET /agent/v1/transfers/:transfer_id — preview (kind-agnostic)
15
+ * POST /agent/v1/transfers/:transfer_id/accept — WALLET completion (recipient SIWX-signs)
16
+ * POST /agent/v1/transfers/:transfer_id/claim EMAIL completion (recipient claims into an org)
17
+ * POST /agent/v1/transfers/:transfer_id/cancel — cancel (kind-agnostic)
18
18
  *
19
19
  * Owner-side mutations against a project with a pending transfer return
20
20
  * 409 `PROJECT_HAS_PENDING_TRANSFER`. The SDK kernel surfaces that as
21
- * {@link TransferFreezeError} so agents can guide the user to cancel.
21
+ * {@link TransferFreezeError} so agents can guide the user to cancel. Calling
22
+ * the wrong completion for a row's kind (e.g. `accept` on an email row) returns
23
+ * 409 `WRONG_COMPLETION_FOR_TRANSFER_KIND`; the thrown error exposes
24
+ * `nextActions` pointing at the sibling completion on the SAME `transfer_id`.
22
25
  */
23
26
  import type { Client } from "../kernel.js";
24
27
  /** Phase 1A only supports the `migrate` policy — B's wallet must already be on a organization, and the project moves into it. */
25
28
  export type TransferBillingPolicy = "migrate";
26
29
  export type TransferStatus = "pending" | "accepted" | "cancelled" | "expired";
27
30
  export type TransferCancelledBy = "from_wallet" | "to_wallet" | "system";
28
- /** Inputs to `r.admin.transfers.initiate(...)`. */
29
- export interface InitiateTransferInput {
30
- /** Project id to transfer. Caller must currently own it (gateway re-checks against fresh DB, not cache). */
31
+ /** Which kind of recipient a transfer row is addressed to. */
32
+ export type RecipientKind = "wallet" | "email";
33
+ /** Initiate a transfer addressed to a wallet (two-party SIWX completion via `accept`). */
34
+ export interface InitiateWalletTransferInput {
35
+ /** Project id to transfer. Caller must currently own/admin it (gateway re-checks against fresh DB, not cache). */
31
36
  projectId: string;
32
37
  /** Recipient wallet (any case — gateway lowercases). Must differ from the current owner. */
33
38
  toWallet: string;
39
+ /** Mutually exclusive with {@link InitiateWalletTransferInput.toWallet}; not allowed on the wallet path. */
40
+ toEmail?: never;
34
41
  /**
35
42
  * Billing policy. Defaults to `"migrate"`. Phase 1A only supports
36
43
  * `"migrate"`; future phases may add `"inherit"` as a separate spec.
@@ -40,7 +47,38 @@ export interface InitiateTransferInput {
40
47
  message?: string;
41
48
  /** Optional KySigned record id (Phase 1A: informational only, stored verbatim, not verified). */
42
49
  kysignedRecordId?: string;
50
+ /** Retention is an email-only opt-in; not allowed on the wallet path. */
51
+ retainCollaborator?: never;
43
52
  }
53
+ /** Initiate a transfer addressed to an email (the recipient claims into an org via `claim`). */
54
+ export interface InitiateEmailTransferInput {
55
+ /** Project id to transfer. Caller must currently own/admin it. */
56
+ projectId: string;
57
+ /** Recipient email; claimed at the recipient's first verified login. */
58
+ toEmail: string;
59
+ /** Mutually exclusive with {@link InitiateEmailTransferInput.toEmail}; not allowed on the email path. */
60
+ toWallet?: never;
61
+ /** Optional note shown to the recipient (HTML-escaped server-side). */
62
+ message?: string;
63
+ /**
64
+ * Opt in (v1.91) to retaining a `developer` membership in the recipient's org
65
+ * after the transfer completes. Only `role: "developer"` is accepted, and the
66
+ * subject is always the initiating owner (you can only retain yourself). The
67
+ * recipient must explicitly accept it at claim time (see
68
+ * {@link ClaimTransferInput.acceptRetainedCollaborator}); omitting this is a
69
+ * full severance, the default.
70
+ */
71
+ retainCollaborator?: {
72
+ role: "developer";
73
+ } | null;
74
+ /** Billing policy is wallet-path only; not allowed on the email path. */
75
+ billingPolicy?: never;
76
+ /** KySigned record id is wallet-path only; not allowed on the email path. */
77
+ kysignedRecordId?: never;
78
+ }
79
+ /** Inputs to `r.admin.transfers.initiate(...)` — wallet XOR email. */
80
+ export type InitiateTransferInput = InitiateWalletTransferInput | InitiateEmailTransferInput;
81
+ /** Result of a wallet-addressed `initiate`. */
44
82
  export interface InitiateTransferResult {
45
83
  transfer_id: string;
46
84
  expires_at: string;
@@ -55,6 +93,13 @@ export interface InitiateTransferResult {
55
93
  lease_refundable: false;
56
94
  terms_sha256: string;
57
95
  }
96
+ /** Result of an email-addressed `initiate`. The recipient completes via `claim`. */
97
+ export interface InitiateEmailTransferResult {
98
+ status: "ok";
99
+ transfer_id: string;
100
+ to_email: string;
101
+ expires_at: string;
102
+ }
58
103
  export interface AcceptTransferResult {
59
104
  project_id: string;
60
105
  from_wallet: string;
@@ -79,20 +124,34 @@ export interface CancelTransferResult {
79
124
  cancellation_reason: string | null;
80
125
  cancelled_at: string;
81
126
  }
82
- /** Summary row used in `/agent/v1/transfers/incoming` and `/outgoing`. */
127
+ /**
128
+ * Summary row used in `/agent/v1/transfers/incoming` and `/outgoing`. The list
129
+ * is kind-agnostic: `recipient_kind` discriminates wallet vs email rows. Wallet
130
+ * rows carry `from_wallet`/`to_wallet`; email rows carry `to_email` +
131
+ * `from_organization_id`.
132
+ */
83
133
  export interface TransferSummary {
84
134
  transfer_id: string;
85
135
  project_id: string;
86
136
  project_name_snapshot: string | null;
87
- from_wallet: string;
88
- to_wallet: string;
137
+ recipient_kind: RecipientKind;
89
138
  billing_policy: TransferBillingPolicy;
90
139
  message: string | null;
91
- initiated_at: string;
92
140
  expires_at: string;
93
- kysigned_record_id: string | null;
94
141
  /** API path for the full preview document. */
95
142
  preview_path: string;
143
+ /** Wallet rows only. */
144
+ from_wallet?: string;
145
+ /** Wallet rows only; `null`/absent for email rows. */
146
+ to_wallet?: string | null;
147
+ /** Wallet rows only. */
148
+ initiated_at?: string;
149
+ /** Wallet rows only. */
150
+ kysigned_record_id?: string | null;
151
+ /** Email rows only. */
152
+ to_email?: string;
153
+ /** Email rows only. */
154
+ from_organization_id?: string | null;
96
155
  }
97
156
  export interface ListTransfersOptions {
98
157
  /** Page size; defaults to 50 on the gateway. */
@@ -137,15 +196,37 @@ export interface BillingImplications {
137
196
  functions_count: number;
138
197
  custom_domains_count: number;
139
198
  }
199
+ /**
200
+ * The sender-retained-membership offer block on an email transfer preview
201
+ * (v1.91), or `null` when the sender requested no retention. `accept_field`
202
+ * names the claim body field the recipient sets to accept
203
+ * (`"accept_retained_collaborator"`).
204
+ */
205
+ export interface RetainCollaboratorPreview {
206
+ principal_id: string;
207
+ role: "developer";
208
+ sender_label: string;
209
+ scope: string;
210
+ note?: string;
211
+ accept_field: string;
212
+ [key: string]: unknown;
213
+ }
214
+ /**
215
+ * Kind-agnostic preview document. Wallet-identity fields are `null` on email
216
+ * rows; `to_email` and `retain_collaborator` are populated on email rows.
217
+ */
140
218
  export interface ProjectTransferPreview {
141
219
  transfer_id: string;
142
220
  project_id: string;
143
221
  project_name_snapshot: string | null;
144
222
  status: TransferStatus;
145
- from_wallet: string;
146
- from_wallet_display: string;
147
- to_wallet: string;
148
- to_wallet_display: string;
223
+ recipient_kind: RecipientKind;
224
+ from_wallet: string | null;
225
+ from_wallet_display: string | null;
226
+ to_wallet: string | null;
227
+ to_wallet_display: string | null;
228
+ /** Email rows only. */
229
+ to_email?: string;
149
230
  billing_policy: TransferBillingPolicy;
150
231
  message: string | null;
151
232
  initiated_at: string;
@@ -162,140 +243,91 @@ export interface ProjectTransferPreview {
162
243
  signers: SignerPreview[];
163
244
  github_repo_note: string;
164
245
  billing_implications: BillingImplications;
165
- }
166
- /** Inputs to {@link Transfers.initiateHandoff}. */
167
- export interface InitiateHandoffInput {
168
- /** Project id to hand off. Caller must currently own it. */
169
- projectId: string;
170
- /** Recipient email; claimed at the recipient's first login. */
171
- toEmail: string;
172
- /** Optional note shown to the recipient (HTML-escaped server-side). */
173
- message?: string;
174
- /**
175
- * Opt in (v1.91) to retaining a `developer` membership in the recipient's org
176
- * after the handoff completes. Only `role: "developer"` is accepted, and the
177
- * subject is always the initiating owner (you can only retain yourself). The
178
- * recipient must explicitly accept it at claim time (see
179
- * {@link ClaimHandoffInput.acceptRetainedCollaborator}); omitting this is a
180
- * full severance, the default. Gateway rejects a bad role with
181
- * `INVALID_RETAIN_ROLE` and a missing actor with `RETAIN_SUBJECT_REQUIRED`.
182
- */
183
- retainCollaborator?: {
184
- role: "developer";
185
- } | null;
186
- }
187
- /** Result of {@link Transfers.initiateHandoff}. Forward-compatible (gateway owns the exact shape). */
188
- export interface HandoffResult {
189
- transfer_id: string;
190
- expires_at?: string;
191
- [key: string]: unknown;
192
- }
193
- /** Summary row from `GET /agent/v1/handoffs/incoming`. Forward-compatible. */
194
- export interface HandoffSummary {
195
- transfer_id: string;
196
- project_id: string;
197
- to_email?: string;
198
- [key: string]: unknown;
199
- }
200
- /**
201
- * The sender-retained-membership offer block on a handoff preview (v1.91), or
202
- * `null` when the sender requested no retention. `accept_field` names the claim
203
- * body field the recipient sets to accept (`"accept_retained_collaborator"`).
204
- */
205
- export interface RetainCollaboratorPreview {
206
- principal_id: string;
207
- role: "developer";
208
- sender_label: string;
209
- scope: string;
210
- note?: string;
211
- accept_field: string;
212
- [key: string]: unknown;
213
- }
214
- /** Preview from `GET /agent/v1/handoffs/:transfer_id`. Forward-compatible. */
215
- export interface ProjectHandoffPreview {
216
- transfer_id: string;
217
- project_id: string;
218
- status?: TransferStatus | string;
219
- /** v1.91 sender-retained-membership offer, or `null` when none was requested. */
246
+ /** v1.91 sender-retained-membership offer (email rows), or `null` when none was requested. */
220
247
  retain_collaborator?: RetainCollaboratorPreview | null;
221
- [key: string]: unknown;
222
248
  }
223
- /** Inputs to {@link Transfers.claimHandoff}. */
224
- export interface ClaimHandoffInput {
249
+ /** Inputs to {@link Transfers.claim}. */
250
+ export interface ClaimTransferInput {
225
251
  /** Org (organization) to claim into. Omit to claim into a brand-new org. */
226
252
  organizationId?: string;
227
253
  /**
228
254
  * Accept the sender's v1.91 retained-`developer`-membership offer (see the
229
- * handoff preview's `retain_collaborator` block). Only an explicit `true`
255
+ * preview's `retain_collaborator` block). Only an explicit `true`
230
256
  * materializes the membership in the new org; omitting it (the default) is a
231
257
  * full severance.
232
258
  */
233
259
  acceptRetainedCollaborator?: boolean;
234
260
  }
235
- /** Result of {@link Transfers.claimHandoff}. Forward-compatible. */
236
- export interface ClaimHandoffResult {
261
+ /**
262
+ * Result of {@link Transfers.claim}. Symmetric with wallet {@link Transfers.accept}:
263
+ * the email completion returns the new owner's project keys
264
+ * (`project-transfer-claim-credentials`), and `claim` persists them to the
265
+ * keystore so the claimant can operate the project immediately.
266
+ */
267
+ export interface ClaimTransferResult {
268
+ status: "accepted";
237
269
  project_id: string;
238
- new_organization_id?: string | null;
270
+ to_organization_id: string;
271
+ created_new_org: boolean;
239
272
  /**
240
273
  * The sender's principal id retained as a `developer` of the new org (v1.91),
241
274
  * or `null` when no membership was retained (declined, not offered, or no-op).
242
275
  */
243
- retained_collaborator_principal_id?: string | null;
244
- [key: string]: unknown;
276
+ retained_collaborator_principal_id: string | null;
277
+ /** New owner's project anon key (stateless `project_id`-derived JWT). `claim` persists it. */
278
+ anon_key: string;
279
+ /** New owner's project service key (stateless `project_id`-derived JWT). Full project access; persisted on claim. */
280
+ service_key: string;
245
281
  }
246
282
  export declare class Transfers {
247
283
  private readonly client;
248
284
  constructor(client: Client);
249
285
  /**
250
- * Initiate a two-party project transfer. Caller must currently own
251
- * `projectId` (gateway re-reads owner from DB, not cache). Creates a
252
- * `pending` row with a 72h expiry and freezes owner-side mutations on
253
- * the project until the transfer is accepted, cancelled, or expires.
286
+ * Initiate a project transfer addressed to a wallet (`toWallet`) OR an email
287
+ * (`toEmail`), exactly one. Caller must currently own/admin `projectId`
288
+ * (gateway re-reads owner from DB, not cache). Creates a `pending` row with a
289
+ * 72h expiry and freezes owner-side mutations on the project until the
290
+ * transfer is accepted (wallet), claimed (email), cancelled, or expires.
254
291
  */
255
- initiate(input: InitiateTransferInput): Promise<InitiateTransferResult>;
292
+ initiate(input: InitiateWalletTransferInput): Promise<InitiateTransferResult>;
293
+ initiate(input: InitiateEmailTransferInput): Promise<InitiateEmailTransferResult>;
256
294
  /**
257
- * Fetch the preview document for a pending or terminal transfer. The
258
- * caller must be either the `from_wallet` or the `to_wallet`; other
259
- * wallets receive 403. Preview lists secret NAMES (not values), custom
260
- * domains, functions, CI bindings that will be revoked at accept, and
261
- * the billing implications.
295
+ * Fetch the preview document for a pending or terminal transfer of either
296
+ * kind. The caller must be a party to it (wallet signer, addressed-email
297
+ * principal, or offering-org member); other callers receive 403. Preview
298
+ * lists secret NAMES (not values), custom domains, functions, CI bindings
299
+ * that will be revoked at completion, the billing implications, and — on
300
+ * email rows — the `retain_collaborator` offer.
262
301
  */
263
302
  preview(transferId: string): Promise<ProjectTransferPreview>;
264
303
  /**
265
- * Accept an incoming transfer. The caller's wallet must equal the
266
- * transfer's `to_wallet`. The accept transaction atomically flips
267
- * ownership, revokes A's CI bindings on the project, enqueues
268
- * notifications to both parties, and stamps the persistent
269
- * `secrets_rotation_advised` advisory on the project.
304
+ * Accept an incoming WALLET transfer. The caller's wallet must equal the
305
+ * transfer's `to_wallet`. The accept transaction atomically flips ownership,
306
+ * revokes A's CI bindings on the project, enqueues notifications to both
307
+ * parties, and stamps the persistent `secrets_rotation_advised` advisory.
270
308
  */
271
309
  accept(transferId: string): Promise<AcceptTransferResult>;
272
310
  /**
273
- * Cancel a pending transfer. The caller must be either the `from_wallet`
274
- * or the `to_wallet`. Already-accepted/cancelled/expired transfers
275
- * return 409 `TRANSFER_ALREADY_PROCESSED`.
311
+ * Claim an incoming EMAIL transfer into an org. Omit `organizationId` to claim
312
+ * into a brand-new org. The claim atomically flips ownership (the email analog
313
+ * of {@link Transfers.accept}) and returns the new owner's project keys, which
314
+ * `claim` persists to the keystore — symmetric with `accept` (#428 /
315
+ * `project-transfer-claim-credentials`) — so the claimant can operate the
316
+ * project immediately. Note the claim auth model is principal-based (a
317
+ * control-plane session or a verified-email SIWX match), so — unlike `accept`
318
+ * — a wallet is not assumed to be present.
319
+ */
320
+ claim(transferId: string, opts?: ClaimTransferInput): Promise<ClaimTransferResult>;
321
+ /**
322
+ * Cancel a pending transfer of either kind. The caller must be authorized for
323
+ * the row's kind (a wallet signer, or an owner/admin of the offering org /
324
+ * the addressed-email principal). Already-processed transfers return 409
325
+ * `TRANSFER_ALREADY_PROCESSED`.
276
326
  */
277
327
  cancel(transferId: string, reason?: string): Promise<CancelTransferResult>;
278
- /** Pending transfers OFFERED TO the authenticated wallet. */
328
+ /** Pending transfers OFFERED TO the caller — both wallet- and email-addressed. */
279
329
  listIncoming(opts?: ListTransfersOptions): Promise<TransferSummary[]>;
280
- /** Pending transfers INITIATED BY the authenticated wallet. */
330
+ /** Pending transfers INITIATED BY the caller — both wallet- and email-addressed. */
281
331
  listOutgoing(opts?: ListTransfersOptions): Promise<TransferSummary[]>;
282
- /**
283
- * Initiate an email→org handoff of `projectId` to `toEmail`. Like a wallet
284
- * transfer, freezes owner-side mutations until the recipient claims, the
285
- * sender cancels, or it expires.
286
- */
287
- initiateHandoff(input: InitiateHandoffInput): Promise<HandoffResult>;
288
- /** Pending handoffs addressed to the authenticated principal's email. */
289
- listIncomingHandoffs(): Promise<HandoffSummary[]>;
290
- /** Preview a handoff (sender, or the addressed recipient). */
291
- previewHandoff(transferId: string): Promise<ProjectHandoffPreview>;
292
- /**
293
- * Claim an incoming handoff into an org. Omit `organizationId` to claim
294
- * into a brand-new org. The claim atomically flips ownership (the handoff
295
- * analog of {@link Transfers.accept}).
296
- */
297
- claimHandoff(transferId: string, input?: ClaimHandoffInput): Promise<ClaimHandoffResult>;
298
- /** Cancel a pending handoff (sender or recipient). */
299
- cancelHandoff(transferId: string): Promise<CancelTransferResult>;
300
332
  }
301
333
  //# sourceMappingURL=transfers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transfers.d.ts","sourceRoot":"","sources":["../../src/namespaces/transfers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transfers.d.ts","sourceRoot":"","sources":["../../src/namespaces/transfers.ts"],"names":[],"mappings":"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"}
@@ -1,67 +1,87 @@
1
1
  /**
2
- * `transfers` namespace — two-party SIWX-signed project transfer (v1.59).
2
+ * `transfers` namespace — the unified project-transfer noun (v1.93+).
3
3
  *
4
- * Exposed as `r.admin.transfers.*`. Phase 1A surface: initiate (owner-only),
5
- * preview, accept (recipient), cancel (either party), and incoming/outgoing
6
- * inboxes. The handoff is atomic at accept time: ownership flips, CI
7
- * bindings are revoked, secret names carry over (values are NOT visible to
8
- * the recipient before accept), and the project is decorated with a
9
- * persistent `secrets_rotation_advised` advisory.
4
+ * Exposed as `r.admin.transfers.*`. Project transfer is ONE capability,
5
+ * body-discriminated by recipient kind: a wallet recipient (`toWallet`, SIWX
6
+ * bilateral signing) or an email recipient (`toEmail`, the recipient claims
7
+ * into an org). Both ride the same `/transfers` surface there is no separate
8
+ * `/handoffs` noun (the gateway removed it in `unify-project-transfer-surface`).
10
9
  *
11
10
  * Gateway endpoints:
12
- * POST /projects/v1/:project_id/transfers — A initiates
13
- * GET /agent/v1/transfers/incoming — B's inbox
14
- * GET /agent/v1/transfers/outgoing — A's outbox
15
- * GET /agent/v1/transfers/:transfer_id — preview (either party)
16
- * POST /agent/v1/transfers/:transfer_id/accept — B accepts
17
- * POST /agent/v1/transfers/:transfer_id/cancel either party cancels
11
+ * POST /projects/v1/:project_id/transfers — initiate; body { to_wallet } XOR { to_email }
12
+ * GET /agent/v1/transfers/incoming — inbox (both kinds, unioned)
13
+ * GET /agent/v1/transfers/outgoing — outbox (both kinds, unioned)
14
+ * GET /agent/v1/transfers/:transfer_id — preview (kind-agnostic)
15
+ * POST /agent/v1/transfers/:transfer_id/accept — WALLET completion (recipient SIWX-signs)
16
+ * POST /agent/v1/transfers/:transfer_id/claim EMAIL completion (recipient claims into an org)
17
+ * POST /agent/v1/transfers/:transfer_id/cancel — cancel (kind-agnostic)
18
18
  *
19
19
  * Owner-side mutations against a project with a pending transfer return
20
20
  * 409 `PROJECT_HAS_PENDING_TRANSFER`. The SDK kernel surfaces that as
21
- * {@link TransferFreezeError} so agents can guide the user to cancel.
21
+ * {@link TransferFreezeError} so agents can guide the user to cancel. Calling
22
+ * the wrong completion for a row's kind (e.g. `accept` on an email row) returns
23
+ * 409 `WRONG_COMPLETION_FOR_TRANSFER_KIND`; the thrown error exposes
24
+ * `nextActions` pointing at the sibling completion on the SAME `transfer_id`.
22
25
  */
26
+ import { LocalError } from "../errors.js";
23
27
  // ─── Class ───────────────────────────────────────────────────────────────────
24
28
  export class Transfers {
25
29
  client;
26
30
  constructor(client) {
27
31
  this.client = client;
28
32
  }
29
- /**
30
- * Initiate a two-party project transfer. Caller must currently own
31
- * `projectId` (gateway re-reads owner from DB, not cache). Creates a
32
- * `pending` row with a 72h expiry and freezes owner-side mutations on
33
- * the project until the transfer is accepted, cancelled, or expires.
34
- */
35
33
  async initiate(input) {
36
- const body = { to_wallet: input.toWallet };
37
- if (input.billingPolicy !== undefined)
38
- body.billing_policy = input.billingPolicy;
39
- if (input.message !== undefined)
40
- body.message = input.message;
41
- if (input.kysignedRecordId !== undefined)
42
- body.kysigned_record_id = input.kysignedRecordId;
43
- return this.client.request(`/projects/v1/${encodeURIComponent(input.projectId)}/transfers`, {
34
+ const toWallet = "toWallet" in input ? input.toWallet : undefined;
35
+ const toEmail = "toEmail" in input ? input.toEmail : undefined;
36
+ const hasWallet = typeof toWallet === "string" && toWallet.length > 0;
37
+ const hasEmail = typeof toEmail === "string" && toEmail.length > 0;
38
+ if (hasWallet === hasEmail) {
39
+ throw new LocalError("Provide exactly one of toWallet or toEmail.", "initiating project transfer", { code: "VALIDATION_ERROR", details: { fields: ["toWallet", "toEmail"] } });
40
+ }
41
+ const path = `/projects/v1/${encodeURIComponent(input.projectId)}/transfers`;
42
+ if (hasEmail) {
43
+ const body = { to_email: toEmail };
44
+ if (input.message !== undefined)
45
+ body.message = input.message;
46
+ const retain = input.retainCollaborator;
47
+ if (retain !== undefined)
48
+ body.retain_collaborator = retain;
49
+ return this.client.request(path, {
50
+ method: "POST",
51
+ body,
52
+ context: "initiating project transfer",
53
+ });
54
+ }
55
+ const w = input;
56
+ const body = { to_wallet: toWallet };
57
+ if (w.billingPolicy !== undefined)
58
+ body.billing_policy = w.billingPolicy;
59
+ if (w.message !== undefined)
60
+ body.message = w.message;
61
+ if (w.kysignedRecordId !== undefined)
62
+ body.kysigned_record_id = w.kysignedRecordId;
63
+ return this.client.request(path, {
44
64
  method: "POST",
45
65
  body,
46
66
  context: "initiating project transfer",
47
67
  });
48
68
  }
49
69
  /**
50
- * Fetch the preview document for a pending or terminal transfer. The
51
- * caller must be either the `from_wallet` or the `to_wallet`; other
52
- * wallets receive 403. Preview lists secret NAMES (not values), custom
53
- * domains, functions, CI bindings that will be revoked at accept, and
54
- * the billing implications.
70
+ * Fetch the preview document for a pending or terminal transfer of either
71
+ * kind. The caller must be a party to it (wallet signer, addressed-email
72
+ * principal, or offering-org member); other callers receive 403. Preview
73
+ * lists secret NAMES (not values), custom domains, functions, CI bindings
74
+ * that will be revoked at completion, the billing implications, and — on
75
+ * email rows — the `retain_collaborator` offer.
55
76
  */
56
77
  async preview(transferId) {
57
78
  return this.client.request(`/agent/v1/transfers/${encodeURIComponent(transferId)}`, { context: "previewing project transfer" });
58
79
  }
59
80
  /**
60
- * Accept an incoming transfer. The caller's wallet must equal the
61
- * transfer's `to_wallet`. The accept transaction atomically flips
62
- * ownership, revokes A's CI bindings on the project, enqueues
63
- * notifications to both parties, and stamps the persistent
64
- * `secrets_rotation_advised` advisory on the project.
81
+ * Accept an incoming WALLET transfer. The caller's wallet must equal the
82
+ * transfer's `to_wallet`. The accept transaction atomically flips ownership,
83
+ * revokes A's CI bindings on the project, enqueues notifications to both
84
+ * parties, and stamps the persistent `secrets_rotation_advised` advisory.
65
85
  */
66
86
  async accept(transferId) {
67
87
  const result = await this.client.request(`/agent/v1/transfers/${encodeURIComponent(transferId)}/accept`, {
@@ -86,9 +106,45 @@ export class Transfers {
86
106
  return result;
87
107
  }
88
108
  /**
89
- * Cancel a pending transfer. The caller must be either the `from_wallet`
90
- * or the `to_wallet`. Already-accepted/cancelled/expired transfers
91
- * return 409 `TRANSFER_ALREADY_PROCESSED`.
109
+ * Claim an incoming EMAIL transfer into an org. Omit `organizationId` to claim
110
+ * into a brand-new org. The claim atomically flips ownership (the email analog
111
+ * of {@link Transfers.accept}) and returns the new owner's project keys, which
112
+ * `claim` persists to the keystore — symmetric with `accept` (#428 /
113
+ * `project-transfer-claim-credentials`) — so the claimant can operate the
114
+ * project immediately. Note the claim auth model is principal-based (a
115
+ * control-plane session or a verified-email SIWX match), so — unlike `accept`
116
+ * — a wallet is not assumed to be present.
117
+ */
118
+ async claim(transferId, opts = {}) {
119
+ const body = {};
120
+ if (opts.organizationId !== undefined)
121
+ body.organization_id = opts.organizationId;
122
+ if (opts.acceptRetainedCollaborator !== undefined) {
123
+ body.accept_retained_collaborator = opts.acceptRetainedCollaborator;
124
+ }
125
+ const result = await this.client.request(`/agent/v1/transfers/${encodeURIComponent(transferId)}/claim`, { method: "POST", body, context: "claiming project transfer" });
126
+ // Persist the new owner's keys so the claimant can operate the project
127
+ // immediately, mirroring `accept`. Keys are returned only after the
128
+ // ownership flip commits, to the authorized claimant.
129
+ if (result.anon_key && result.service_key) {
130
+ const creds = this.client.credentials;
131
+ if (creds.saveProject) {
132
+ await creds.saveProject(result.project_id, {
133
+ anon_key: result.anon_key,
134
+ service_key: result.service_key,
135
+ });
136
+ }
137
+ if (creds.setActiveProject) {
138
+ await creds.setActiveProject(result.project_id);
139
+ }
140
+ }
141
+ return result;
142
+ }
143
+ /**
144
+ * Cancel a pending transfer of either kind. The caller must be authorized for
145
+ * the row's kind (a wallet signer, or an owner/admin of the offering org /
146
+ * the addressed-email principal). Already-processed transfers return 409
147
+ * `TRANSFER_ALREADY_PROCESSED`.
92
148
  */
93
149
  async cancel(transferId, reason) {
94
150
  const body = {};
@@ -100,7 +156,7 @@ export class Transfers {
100
156
  context: "cancelling project transfer",
101
157
  });
102
158
  }
103
- /** Pending transfers OFFERED TO the authenticated wallet. */
159
+ /** Pending transfers OFFERED TO the caller — both wallet- and email-addressed. */
104
160
  async listIncoming(opts = {}) {
105
161
  const q = buildPagination(opts);
106
162
  const path = q ? `/agent/v1/transfers/incoming?${q}` : "/agent/v1/transfers/incoming";
@@ -109,7 +165,7 @@ export class Transfers {
109
165
  });
110
166
  return res.transfers;
111
167
  }
112
- /** Pending transfers INITIATED BY the authenticated wallet. */
168
+ /** Pending transfers INITIATED BY the caller — both wallet- and email-addressed. */
113
169
  async listOutgoing(opts = {}) {
114
170
  const q = buildPagination(opts);
115
171
  const path = q ? `/agent/v1/transfers/outgoing?${q}` : "/agent/v1/transfers/outgoing";
@@ -118,51 +174,6 @@ export class Transfers {
118
174
  });
119
175
  return res.transfers;
120
176
  }
121
- // ── Email→org handoff (v1.78) ─────────────────────────────────────────────
122
- // Same transfer rail, but the recipient is an EMAIL (resolved to an org at
123
- // claim time) rather than a wallet. The caller must own the project; the
124
- // recipient claims into an org they own (or a brand-new one). Exposed under
125
- // the same `transfer` noun on the CLI (`transfer init --to <email>`).
126
- /**
127
- * Initiate an email→org handoff of `projectId` to `toEmail`. Like a wallet
128
- * transfer, freezes owner-side mutations until the recipient claims, the
129
- * sender cancels, or it expires.
130
- */
131
- async initiateHandoff(input) {
132
- const body = { to_email: input.toEmail };
133
- if (input.message !== undefined)
134
- body.message = input.message;
135
- if (input.retainCollaborator !== undefined)
136
- body.retain_collaborator = input.retainCollaborator;
137
- return this.client.request(`/projects/v1/${encodeURIComponent(input.projectId)}/handoffs`, { method: "POST", body, context: "initiating project handoff" });
138
- }
139
- /** Pending handoffs addressed to the authenticated principal's email. */
140
- async listIncomingHandoffs() {
141
- const res = await this.client.request("/agent/v1/handoffs/incoming", { context: "listing incoming handoffs" });
142
- return res.handoffs ?? res.transfers ?? [];
143
- }
144
- /** Preview a handoff (sender, or the addressed recipient). */
145
- async previewHandoff(transferId) {
146
- return this.client.request(`/agent/v1/handoffs/${encodeURIComponent(transferId)}`, { context: "previewing project handoff" });
147
- }
148
- /**
149
- * Claim an incoming handoff into an org. Omit `organizationId` to claim
150
- * into a brand-new org. The claim atomically flips ownership (the handoff
151
- * analog of {@link Transfers.accept}).
152
- */
153
- async claimHandoff(transferId, input = {}) {
154
- const body = {};
155
- if (input.organizationId !== undefined)
156
- body.organization_id = input.organizationId;
157
- if (input.acceptRetainedCollaborator !== undefined) {
158
- body.accept_retained_collaborator = input.acceptRetainedCollaborator;
159
- }
160
- return this.client.request(`/agent/v1/handoffs/${encodeURIComponent(transferId)}/claim`, { method: "POST", body, context: "claiming project handoff" });
161
- }
162
- /** Cancel a pending handoff (sender or recipient). */
163
- async cancelHandoff(transferId) {
164
- return this.client.request(`/agent/v1/handoffs/${encodeURIComponent(transferId)}/cancel`, { method: "POST", body: {}, context: "cancelling project handoff" });
165
- }
166
177
  }
167
178
  function buildPagination(opts) {
168
179
  const parts = [];
@@ -1 +1 @@
1
- {"version":3,"file":"transfers.js","sourceRoot":"","sources":["../../src/namespaces/transfers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transfers.js","sourceRoot":"","sources":["../../src/namespaces/transfers.ts"],"names":[],"mappings":"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"}