run402 4.93.2 → 4.94.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/README.md +43 -41
- package/cli.mjs +34 -29
- package/core-dist/config.js +52 -18
- package/core-dist/control-plane-session.js +31 -6
- package/core-dist/keystore.js +7 -7
- package/core-dist/profiles.js +9 -7
- package/core-dist/{allowance-auth.js → wallet-auth.js} +15 -15
- package/{sdk/core-dist/allowance.js → core-dist/wallet.js} +20 -20
- package/{sdk/core-dist/write-auth-session.js → core-dist/write-approvals.js} +19 -19
- package/gitvault-surface.json +1 -1
- package/lib/admin.mjs +1 -1
- package/lib/agent.mjs +20 -18
- package/lib/approve.mjs +81 -0
- package/lib/apps.mjs +3 -3
- package/lib/assets.mjs +2 -2
- package/lib/billing.mjs +6 -6
- package/lib/buzz-doctor.mjs +1 -1
- package/lib/buzz-notifications.mjs +1 -1
- package/lib/buzz.mjs +1 -1
- package/lib/buzz.test.mjs +1 -1
- package/lib/ci.mjs +4 -4
- package/lib/cold-start.mjs +21 -21
- package/lib/command-manifest.mjs +20 -34
- package/lib/config.mjs +24 -24
- package/lib/contacts.mjs +13 -13
- package/lib/contracts.mjs +1 -1
- package/lib/credentials.mjs +2 -2
- package/lib/daemon-path.mjs +1 -1
- package/lib/delegates.mjs +1 -1
- package/lib/deliveries.mjs +4 -4
- package/lib/deploy-rehearse-discovery.test.mjs +7 -7
- package/lib/deploy-v2.mjs +232 -184
- package/lib/deploy.mjs +21 -53
- package/lib/doctor-source-scan.mjs +1 -1
- package/lib/doctor.mjs +57 -57
- package/lib/escalations.mjs +1 -1
- package/lib/feedback.mjs +10 -10
- package/lib/gitvault-daemon.mjs +1 -1
- package/lib/image.mjs +3 -3
- package/lib/init.mjs +66 -66
- package/lib/lightning-wallet.mjs +28 -28
- package/lib/login.mjs +207 -0
- package/lib/logout.mjs +53 -0
- package/lib/next-actions.mjs +15 -15
- package/lib/org.mjs +100 -13
- package/lib/pay.mjs +1 -1
- package/lib/projects.mjs +26 -29
- package/lib/redeem.mjs +7 -8
- package/lib/remote-helper-session.mjs +12 -12
- package/lib/repos.mjs +62 -62
- package/lib/rooms.mjs +103 -67
- package/lib/sdk-errors.mjs +9 -4
- package/lib/sdk.mjs +3 -3
- package/lib/service.mjs +5 -5
- package/lib/session-proofs.mjs +21 -0
- package/lib/sign-in.mjs +296 -0
- package/lib/sites.mjs +8 -8
- package/lib/stats.mjs +2 -2
- package/lib/status.mjs +25 -25
- package/lib/subdomains.mjs +19 -19
- package/lib/subscriptions.mjs +8 -8
- package/lib/tier.mjs +29 -22
- package/lib/transfer.mjs +58 -85
- package/lib/up.mjs +7 -7
- package/lib/wallet-context.mjs +3 -3
- package/lib/wallet-context.test.mjs +3 -3
- package/lib/wallets.mjs +196 -31
- package/lib/webhook-secret.mjs +6 -6
- package/lib/whoami.mjs +75 -0
- package/package.json +1 -1
- package/sdk/core-dist/config.js +52 -18
- package/sdk/core-dist/control-plane-session.js +31 -6
- package/sdk/core-dist/keystore.js +7 -7
- package/sdk/core-dist/profiles.js +9 -7
- package/sdk/core-dist/{allowance-auth.js → wallet-auth.js} +15 -15
- package/{core-dist/allowance.js → sdk/core-dist/wallet.js} +20 -20
- package/{core-dist/write-auth-session.js → sdk/core-dist/write-approvals.js} +19 -19
- package/sdk/dist/actions.d.ts +1 -1
- package/sdk/dist/actions.d.ts.map +1 -1
- package/sdk/dist/control-plane-credentials.d.ts +8 -8
- package/sdk/dist/control-plane-credentials.js +7 -7
- package/sdk/dist/credentials.d.ts +19 -19
- package/sdk/dist/credentials.d.ts.map +1 -1
- package/sdk/dist/credentials.js +1 -1
- package/sdk/dist/errors.d.ts +24 -26
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js +34 -37
- package/sdk/dist/errors.js.map +1 -1
- package/sdk/dist/index.d.ts +29 -16
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +29 -16
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/kernel.d.ts +1 -1
- package/sdk/dist/kernel.d.ts.map +1 -1
- package/sdk/dist/kernel.js +10 -9
- package/sdk/dist/kernel.js.map +1 -1
- package/sdk/dist/namespaces/admin.d.ts +51 -120
- package/sdk/dist/namespaces/admin.d.ts.map +1 -1
- package/sdk/dist/namespaces/admin.js +41 -45
- package/sdk/dist/namespaces/admin.js.map +1 -1
- package/sdk/dist/namespaces/agent.d.ts +2 -2
- package/sdk/dist/namespaces/agent.d.ts.map +1 -1
- package/sdk/dist/namespaces/agent.js +2 -2
- package/sdk/dist/namespaces/agent.js.map +1 -1
- package/sdk/dist/namespaces/ai.d.ts +1 -1
- package/sdk/dist/namespaces/ai.js +1 -1
- package/sdk/dist/namespaces/billing.d.ts +6 -3
- package/sdk/dist/namespaces/billing.d.ts.map +1 -1
- package/sdk/dist/namespaces/billing.js.map +1 -1
- package/sdk/dist/namespaces/buzz-notifications.types.d.ts +1 -1
- package/sdk/dist/namespaces/buzz.d.ts +2 -2
- package/sdk/dist/namespaces/buzz.d.ts.map +1 -1
- package/sdk/dist/namespaces/buzz.js +2 -2
- package/sdk/dist/namespaces/buzz.js.map +1 -1
- package/sdk/dist/namespaces/buzz.types.d.ts +2 -2
- package/sdk/dist/namespaces/buzz.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/credentials.types.d.ts +1 -1
- package/sdk/dist/namespaces/deploy.d.ts +1 -1
- package/sdk/dist/namespaces/deploy.js +5 -5
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +4 -4
- package/sdk/dist/namespaces/escalations.d.ts +1 -1
- package/sdk/dist/namespaces/escalations.js +1 -1
- package/sdk/dist/namespaces/escalations.types.d.ts +2 -2
- package/sdk/dist/namespaces/escalations.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/events.types.d.ts +1 -1
- package/sdk/dist/namespaces/functions.d.ts +1 -1
- package/sdk/dist/namespaces/functions.js +1 -1
- package/sdk/dist/namespaces/gitvault.crypto.d.ts +1 -1
- package/sdk/dist/namespaces/gitvault.d.ts +24 -24
- package/sdk/dist/namespaces/gitvault.d.ts.map +1 -1
- package/sdk/dist/namespaces/gitvault.js +109 -109
- package/sdk/dist/namespaces/gitvault.js.map +1 -1
- package/sdk/dist/namespaces/me.d.ts +120 -0
- package/sdk/dist/namespaces/me.d.ts.map +1 -0
- package/sdk/dist/namespaces/me.js +34 -0
- package/sdk/dist/namespaces/me.js.map +1 -0
- package/sdk/dist/namespaces/org.d.ts +108 -6
- package/sdk/dist/namespaces/org.d.ts.map +1 -1
- package/sdk/dist/namespaces/org.js +63 -7
- package/sdk/dist/namespaces/org.js.map +1 -1
- package/sdk/dist/namespaces/org.types.d.ts +29 -9
- package/sdk/dist/namespaces/org.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/pay.js +3 -3
- package/sdk/dist/namespaces/pay.js.map +1 -1
- package/sdk/dist/namespaces/projects.d.ts +9 -9
- package/sdk/dist/namespaces/projects.js +15 -15
- package/sdk/dist/namespaces/projects.js.map +1 -1
- package/sdk/dist/namespaces/projects.types.d.ts +28 -12
- package/sdk/dist/namespaces/projects.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/rooms.d.ts +7 -7
- package/sdk/dist/namespaces/rooms.js +17 -17
- package/sdk/dist/namespaces/rooms.js.map +1 -1
- package/sdk/dist/namespaces/rooms.types.d.ts +9 -9
- package/sdk/dist/namespaces/rooms.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/service.d.ts +1 -1
- package/sdk/dist/namespaces/service.js +1 -1
- package/sdk/dist/namespaces/{operator-session.d.ts → session.d.ts} +135 -51
- package/sdk/dist/namespaces/session.d.ts.map +1 -0
- package/sdk/dist/namespaces/{operator-session.js → session.js} +118 -30
- package/sdk/dist/namespaces/session.js.map +1 -0
- package/sdk/dist/namespaces/subdomains.d.ts +5 -5
- package/sdk/dist/namespaces/subdomains.d.ts.map +1 -1
- package/sdk/dist/namespaces/subdomains.js +6 -6
- package/sdk/dist/namespaces/subdomains.js.map +1 -1
- package/sdk/dist/namespaces/tier.d.ts +43 -20
- package/sdk/dist/namespaces/tier.d.ts.map +1 -1
- package/sdk/dist/namespaces/tier.js +7 -7
- package/sdk/dist/namespaces/tier.js.map +1 -1
- package/sdk/dist/namespaces/transfers.d.ts +74 -71
- package/sdk/dist/namespaces/transfers.d.ts.map +1 -1
- package/sdk/dist/namespaces/transfers.js +31 -38
- package/sdk/dist/namespaces/transfers.js.map +1 -1
- package/sdk/dist/namespaces/vouchers.d.ts +9 -10
- package/sdk/dist/namespaces/vouchers.d.ts.map +1 -1
- package/sdk/dist/namespaces/vouchers.js +4 -5
- package/sdk/dist/namespaces/vouchers.js.map +1 -1
- package/sdk/dist/namespaces/wallets.d.ts +72 -3
- package/sdk/dist/namespaces/wallets.d.ts.map +1 -1
- package/sdk/dist/namespaces/wallets.js +141 -3
- package/sdk/dist/namespaces/wallets.js.map +1 -1
- package/sdk/dist/namespaces/write-approval.d.ts +101 -0
- package/sdk/dist/namespaces/write-approval.d.ts.map +1 -0
- package/sdk/dist/namespaces/write-approval.js +62 -0
- package/sdk/dist/namespaces/write-approval.js.map +1 -0
- package/sdk/dist/node/actions-node.d.ts +3 -3
- package/sdk/dist/node/actions-node.d.ts.map +1 -1
- package/sdk/dist/node/actions-node.js +36 -36
- package/sdk/dist/node/actions-node.js.map +1 -1
- package/sdk/dist/node/{bearer-claim-key.d.ts → bearer-redeem-key.d.ts} +12 -12
- package/sdk/dist/node/bearer-redeem-key.d.ts.map +1 -0
- package/sdk/dist/node/{bearer-claim-key.js → bearer-redeem-key.js} +21 -21
- package/sdk/dist/node/bearer-redeem-key.js.map +1 -0
- package/sdk/dist/node/ci.d.ts +1 -1
- package/sdk/dist/node/ci.d.ts.map +1 -1
- package/sdk/dist/node/ci.js +6 -6
- package/sdk/dist/node/ci.js.map +1 -1
- package/sdk/dist/node/credentials.d.ts +17 -16
- package/sdk/dist/node/credentials.d.ts.map +1 -1
- package/sdk/dist/node/credentials.js +28 -27
- package/sdk/dist/node/credentials.js.map +1 -1
- package/sdk/dist/node/funding-recovery.d.ts +1 -1
- package/sdk/dist/node/funding-recovery.d.ts.map +1 -1
- package/sdk/dist/node/funding-recovery.js +1 -1
- package/sdk/dist/node/funding-recovery.js.map +1 -1
- package/sdk/dist/node/gitvault-apply.d.ts +1 -1
- package/sdk/dist/node/gitvault-apply.d.ts.map +1 -1
- package/sdk/dist/node/gitvault-handoff.d.ts +22 -22
- package/sdk/dist/node/gitvault-handoff.d.ts.map +1 -1
- package/sdk/dist/node/gitvault-handoff.js +45 -45
- package/sdk/dist/node/gitvault-handoff.js.map +1 -1
- package/sdk/dist/node/gitvault-prewarm.js +7 -7
- package/sdk/dist/node/gitvault-prewarm.js.map +1 -1
- package/sdk/dist/node/gitvault-restore.d.ts +1 -1
- package/sdk/dist/node/gitvault-restore.js +1 -1
- package/sdk/dist/node/index.d.ts +16 -16
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +15 -15
- package/sdk/dist/node/index.js.map +1 -1
- package/sdk/dist/node/org-adopt.d.ts +49 -0
- package/sdk/dist/node/org-adopt.d.ts.map +1 -0
- package/sdk/dist/node/org-adopt.js +77 -0
- package/sdk/dist/node/org-adopt.js.map +1 -0
- package/sdk/dist/node/paid-fetch.d.ts +7 -7
- package/sdk/dist/node/paid-fetch.d.ts.map +1 -1
- package/sdk/dist/node/paid-fetch.js +54 -54
- package/sdk/dist/node/paid-fetch.js.map +1 -1
- package/sdk/dist/node/preflight.d.ts +1 -1
- package/sdk/dist/node/preflight.d.ts.map +1 -1
- package/sdk/dist/node/preflight.js +1 -1
- package/sdk/dist/node/preflight.js.map +1 -1
- package/sdk/dist/node/source-scan.d.ts +1 -1
- package/sdk/dist/node/source-scan.js +2 -2
- package/sdk/dist/node/source-scan.js.map +1 -1
- package/sdk/dist/scoped.d.ts +3 -3
- package/sdk/dist/scoped.d.ts.map +1 -1
- package/sdk/dist/scoped.js +2 -2
- package/sdk/dist/scoped.js.map +1 -1
- package/core-dist/operator-session.js +0 -154
- package/lib/allowance.mjs +0 -355
- package/lib/operator-proofs.mjs +0 -22
- package/lib/operator.mjs +0 -771
- package/sdk/core-dist/operator-session.js +0 -154
- package/sdk/dist/namespaces/allowance.d.ts +0 -79
- package/sdk/dist/namespaces/allowance.d.ts.map +0 -1
- package/sdk/dist/namespaces/allowance.js +0 -149
- package/sdk/dist/namespaces/allowance.js.map +0 -1
- package/sdk/dist/namespaces/operator-session.d.ts.map +0 -1
- package/sdk/dist/namespaces/operator-session.js.map +0 -1
- package/sdk/dist/namespaces/operator.d.ts +0 -359
- package/sdk/dist/namespaces/operator.d.ts.map +0 -1
- package/sdk/dist/namespaces/operator.js +0 -272
- package/sdk/dist/namespaces/operator.js.map +0 -1
- package/sdk/dist/node/bearer-claim-key.d.ts.map +0 -1
- package/sdk/dist/node/bearer-claim-key.js.map +0 -1
- package/sdk/dist/node/operator-claim.d.ts +0 -49
- package/sdk/dist/node/operator-claim.d.ts.map +0 -1
- package/sdk/dist/node/operator-claim.js +0 -77
- package/sdk/dist/node/operator-claim.js.map +0 -1
package/lib/redeem.mjs
CHANGED
|
@@ -2,14 +2,13 @@ import { getSdk } from "./sdk.mjs";
|
|
|
2
2
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
3
3
|
import { assertKnownFlags, normalizeArgv, positionalArgs } from "./argparse.mjs";
|
|
4
4
|
|
|
5
|
-
const HELP = `run402 redeem — Redeem a promo code
|
|
5
|
+
const HELP = `run402 redeem — Redeem a promo code into your organization's allowance
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
8
|
run402 redeem <code> [--json]
|
|
9
9
|
|
|
10
|
-
A promo code
|
|
11
|
-
|
|
12
|
-
on-chain payment.
|
|
10
|
+
A promo code adds to your organization's allowance, which spends like any
|
|
11
|
+
other allowance — a tier purchase settles from it with no on-chain payment.
|
|
13
12
|
|
|
14
13
|
Notes:
|
|
15
14
|
- Order does not matter. This works as your very first authenticated call
|
|
@@ -17,7 +16,7 @@ Notes:
|
|
|
17
16
|
- Codes are forgiving: case-insensitive and hyphens are optional, so
|
|
18
17
|
'R402-K8F3-Q2W9' and 'r402k8f3q2w9' are the same code.
|
|
19
18
|
- Retrying is safe. A repeat by the same organization returns the original
|
|
20
|
-
result with "already_redeemed": true and never
|
|
19
|
+
result with "already_redeemed": true and never adds the amount twice.
|
|
21
20
|
- Being in a grace state does not block you. Redeeming is how an owner funds
|
|
22
21
|
a renewal, so it is never gated.
|
|
23
22
|
- One gift per organization, per issuer: past the lifetime ceiling for a
|
|
@@ -64,10 +63,10 @@ export async function run(args = []) {
|
|
|
64
63
|
// in a field a human skims past.
|
|
65
64
|
console.error("");
|
|
66
65
|
console.error(
|
|
67
|
-
` Voucher ${usd(data.amount_usd_micros)}
|
|
68
|
-
`${data.already_redeemed ? " (already redeemed " + data.redeemed_at + " —
|
|
66
|
+
` Voucher ${usd(data.amount_usd_micros)} added` +
|
|
67
|
+
`${data.already_redeemed ? " (already redeemed " + data.redeemed_at + " — not added twice)" : ""}`,
|
|
69
68
|
);
|
|
70
|
-
console.error(`
|
|
69
|
+
console.error(` Allowance ${usd(data.balance_usd_micros)}`);
|
|
71
70
|
const next = Array.isArray(data.next_actions) ? data.next_actions.find((a) => a?.cli) : null;
|
|
72
71
|
if (next?.cli) console.error(`\n Next: ${next.cli}`);
|
|
73
72
|
console.error("");
|
|
@@ -146,7 +146,7 @@ const { getSdk } = await sdkModP;
|
|
|
146
146
|
const { resolveWalletCore, enforceWalletExistsCore, WalletSelectionError } = await walletModP;
|
|
147
147
|
const { gitvaultRemoteAddressForm, gitvaultSlugReleasedInfo, parseGitvaultRemoteUrl, gitvaultDegradedReadNote } = await isoModP;
|
|
148
148
|
const { GITVAULT_R402_REF_NAMESPACE, hardenedGit, resolveGitInvocationRepo, readPinnedGitvaultRepo, pinGitvaultRepo, readGitvaultRestoreMarker, readGitvaultAutoGcThreshold, predialGitvaultObjectStore } = await nodeModP;
|
|
149
|
-
const {
|
|
149
|
+
const { walletFile, projectCredentialsFile, profileStateFile } = await configModP;
|
|
150
150
|
|
|
151
151
|
/**
|
|
152
152
|
* Per-session SDK construction cache (gitvault-first-op-premium task 2.2).
|
|
@@ -167,10 +167,10 @@ const { allowanceFile, projectCredentialsFile, profileStateFile } = await config
|
|
|
167
167
|
* doc comment calls out as reasons a fresh instance mattered for tests that
|
|
168
168
|
* mutate them between calls in one process) and INVALIDATED on the mtime of
|
|
169
169
|
* the three files whose bytes actually determine signer/credential material
|
|
170
|
-
* (
|
|
170
|
+
* (wallet, project-credentials keystore, profile state) — a wallet
|
|
171
171
|
* rotation, `run402 init`, or any other on-disk change is picked up on the
|
|
172
172
|
* very next call, no daemon restart required. A file that does not exist
|
|
173
|
-
* yet (fresh wallet, no
|
|
173
|
+
* yet (fresh wallet, no local wallet) signs into the key as `null`, so its
|
|
174
174
|
* LATER appearance also busts the cache. The in-process fallback host calls
|
|
175
175
|
* this at most once per process anyway, so it degrades to exactly today's
|
|
176
176
|
* behavior there — this only changes anything for the daemon.
|
|
@@ -189,7 +189,7 @@ function sdkCacheKey() {
|
|
|
189
189
|
const wallet = process.env.RUN402_WALLET ?? "";
|
|
190
190
|
const configDir = process.env.RUN402_CONFIG_DIR ?? "";
|
|
191
191
|
const apiBase = process.env.RUN402_API_BASE ?? "";
|
|
192
|
-
const files = [mtimeOf(
|
|
192
|
+
const files = [mtimeOf(walletFile()), mtimeOf(projectCredentialsFile()), mtimeOf(profileStateFile())];
|
|
193
193
|
return `${wallet} ${configDir} ${apiBase} ${files.join(",")}`;
|
|
194
194
|
}
|
|
195
195
|
|
|
@@ -214,7 +214,7 @@ const note = (line) => process.stderr.write(`git-remote-run402: ${line}\n`);
|
|
|
214
214
|
* selection at all — a `.run402.json` binding, and even the global
|
|
215
215
|
* `wallets use` default, would silently never reach it; only the
|
|
216
216
|
* `RUN402_WALLET` env layer would work, so a bound checkout's `git push
|
|
217
|
-
* run402 main` would use the WRONG
|
|
217
|
+
* run402 main` would use the WRONG (usually empty) wallet.
|
|
218
218
|
*
|
|
219
219
|
* Shares `resolveWalletCore`/`enforceWalletExistsCore` with the CLI
|
|
220
220
|
* (`cli/lib/wallet-context.mjs`) — ONE implementation, minus the CLI's
|
|
@@ -253,19 +253,19 @@ function walletSourceLabel(resolved) {
|
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
/**
|
|
256
|
-
* The
|
|
256
|
+
* The wallet-missing/malformed family (`core/src/wallet.ts`'s own
|
|
257
257
|
* throws) all end with "Back up the file and run 'run402 init' to recreate
|
|
258
258
|
* it." — a remedy that assumes the resolved wallet is the one you meant.
|
|
259
259
|
* That is only true when NOTHING selected a wallet (the bare default); when
|
|
260
260
|
* an env var or a binding DID name one, the remedy is actively harmful —
|
|
261
|
-
* `run402 init` recreates the DEFAULT wallet's
|
|
262
|
-
* wallet than the one that was actually resolved and whose
|
|
261
|
+
* `run402 init` recreates the DEFAULT wallet's key file, a DIFFERENT
|
|
262
|
+
* wallet than the one that was actually resolved and whose key file is
|
|
263
263
|
* actually missing/broken. Replace
|
|
264
264
|
* it with the resolved wallet's name and how selection works, so the fix is
|
|
265
265
|
* "correct the selection" rather than "recreate the wrong wallet".
|
|
266
266
|
*/
|
|
267
|
-
function
|
|
268
|
-
if (!resolvedWallet || !/
|
|
267
|
+
function enrichWalletError(message) {
|
|
268
|
+
if (!resolvedWallet || !/wallet\.json/.test(message)) return message;
|
|
269
269
|
const source = walletSourceLabel(resolvedWallet);
|
|
270
270
|
const stripped = message.replace(/\s*Back up the file and run 'run402 init' to recreate it\.?/, "").trim();
|
|
271
271
|
if (!source) {
|
|
@@ -276,13 +276,13 @@ function enrichAllowanceError(message) {
|
|
|
276
276
|
return (
|
|
277
277
|
`${stripped} Resolved wallet '${resolvedWallet.name}' via ${source} ` +
|
|
278
278
|
"(order: RUN402_WALLET env > .run402.json binding > 'wallets use' default > default). " +
|
|
279
|
-
`Wrong wallet? Fix selection instead. Right wallet, just
|
|
279
|
+
`Wrong wallet? Fix selection instead. Right wallet, just not created yet? 'run402 wallets new ${resolvedWallet.name}'.`
|
|
280
280
|
);
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
function describeError(err) {
|
|
284
284
|
const code = err?.code ?? err?.body?.code ?? null;
|
|
285
|
-
const message =
|
|
285
|
+
const message = enrichWalletError(err?.message ?? err?.body?.message ?? String(err));
|
|
286
286
|
// SLUG_RELEASED is never auto-followed — but the successor slug (design D6)
|
|
287
287
|
// is exactly the fact a human/agent reading stderr needs to act on it.
|
|
288
288
|
const released = gitvaultSlugReleasedInfo(err);
|
package/lib/repos.mjs
CHANGED
|
@@ -25,12 +25,12 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
25
25
|
import { basename, join } from "node:path";
|
|
26
26
|
import { getSdk } from "./sdk.mjs";
|
|
27
27
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
28
|
-
import { withAutoApprove } from "./
|
|
29
|
-
import {
|
|
28
|
+
import { withAutoApprove } from "./sign-in.mjs";
|
|
29
|
+
import { walletAuthHeaders, isCoreApiTarget, readWallet, resolveProjectId } from "./config.mjs";
|
|
30
30
|
import { loadLiveControlPlaneSession } from "../core-dist/control-plane-session.js";
|
|
31
31
|
import { resolveOrgId, resolveOwningOrgId } from "./org-context.mjs";
|
|
32
32
|
import { resolveGitvaultTarget } from "./gitvault-target.mjs";
|
|
33
|
-
import { nextAction,
|
|
33
|
+
import { nextAction, setOrgSlugAction, setRepoNameAction } from "./next-actions.mjs";
|
|
34
34
|
import { resolveHarnessLabels, resolveSessionKey, resolveTaskLabel, persistSessionKey } from "./harness-context.mjs";
|
|
35
35
|
import { updateRoomState } from "./rooms-context.mjs";
|
|
36
36
|
import { printKeystoreLocation } from "./gitvault.mjs";
|
|
@@ -132,7 +132,7 @@ Subcommands:
|
|
|
132
132
|
no payload copy at all); \`run402 repos mirror <destination>\`
|
|
133
133
|
still works unchanged as your second customer-held location.
|
|
134
134
|
On a machine with no wallet, or a wallet with no active tier, this folds the cold-start
|
|
135
|
-
chain (
|
|
135
|
+
chain (wallet -> faucet -> one x402 prototype payment,
|
|
136
136
|
announced) before retrying once; \`--no-init\` opts out.
|
|
137
137
|
view Side-effect-free: what this machine and the control plane each
|
|
138
138
|
believe about the repo — allocation, policy, whether this keystore
|
|
@@ -162,11 +162,11 @@ Subcommands:
|
|
|
162
162
|
<handoff_id>\` read/revoke instead of minting.
|
|
163
163
|
resume Resume a Handoff Key on ANY machine: parses the key; on a wallet
|
|
164
164
|
with no active tier first folds the same cold-start chain
|
|
165
|
-
\`create\` does (
|
|
165
|
+
\`create\` does (wallet → faucet → one x402 prototype payment,
|
|
166
166
|
each step announced) so the resumed agent arrives as a paid-up
|
|
167
167
|
run402 wallet of its own — \`--no-init\` opts out, and because the
|
|
168
|
-
|
|
169
|
-
blocks the resume); then
|
|
168
|
+
redemption itself needs no tier a chain failure is reported (never
|
|
169
|
+
blocks the resume); then redeems the key with THIS machine's own
|
|
170
170
|
wallet, clones the vault at the base HEAD
|
|
171
171
|
into \`--to <dir>\` (default: the vault's name), applies the
|
|
172
172
|
stash-shaped checkpoint (staged/unstaged/deleted/untracked
|
|
@@ -188,10 +188,10 @@ Subcommands:
|
|
|
188
188
|
whose key is not admitted is refused
|
|
189
189
|
\`INVITE_MINT_REQUIRES_WRITER\` — have a live writer run
|
|
190
190
|
\`run402 repos access sync\` (any push does it too), then retry.
|
|
191
|
-
join
|
|
192
|
-
\`resume\` runs (
|
|
191
|
+
join Redeem an Invite Key on ANY machine: the SAME cold-start fold
|
|
192
|
+
\`resume\` runs (wallet → faucet → one x402 prototype payment,
|
|
193
193
|
announced — \`--no-init\` opts out; a chain failure never blocks
|
|
194
|
-
the
|
|
194
|
+
the redemption), clones the vault at the base HEAD into \`--to <dir>\`
|
|
195
195
|
(default: the vault's name), restores the stash-shaped
|
|
196
196
|
checkpoint exactly like \`resume\`, pins \`r402.room\` to the
|
|
197
197
|
INVITE's own room, adds \`.run402/\` to \`.git/info/exclude\`,
|
|
@@ -275,8 +275,8 @@ Subcommands:
|
|
|
275
275
|
cwd unless \`--out\` says otherwise (\`--out -\` prints only); the
|
|
276
276
|
full JSON always goes to stdout. Principal-scoped, not
|
|
277
277
|
repo-scoped (one bundle covers every vault you can read) — auth
|
|
278
|
-
is your
|
|
279
|
-
|
|
278
|
+
is your sign-in session (\`run402 login\` first; without one
|
|
279
|
+
it answers for the active
|
|
280
280
|
WALLET's agent principal, normally no wrappers, and says so).
|
|
281
281
|
To make it travel WITH a mirror, copy it to
|
|
282
282
|
member-recovery-bundles/<name>.json under the mirrored prefix —
|
|
@@ -851,7 +851,7 @@ async function printCreateResult({ sdk, projectId, vault, adopted, name, verbose
|
|
|
851
851
|
}
|
|
852
852
|
}
|
|
853
853
|
} catch (err) {
|
|
854
|
-
if (name) console.error(`repo name not
|
|
854
|
+
if (name) console.error(`repo name not set (non-fatal): ${err?.message ?? String(err)}`);
|
|
855
855
|
}
|
|
856
856
|
|
|
857
857
|
// A `push_repo` action names a remote that EXISTS — only a scaffolded
|
|
@@ -863,7 +863,7 @@ async function printCreateResult({ sdk, projectId, vault, adopted, name, verbose
|
|
|
863
863
|
? nextAction("push_repo", { command: `git push -u ${vault.remote.name} HEAD`, why: "Publish the current branch to the encrypted Run402 remote." })
|
|
864
864
|
: null;
|
|
865
865
|
const remoteSkippedActions = vault.remote?.status === "skipped" ? (vault.remote.next_actions ?? []) : [];
|
|
866
|
-
const
|
|
866
|
+
const nameAction = address ? null : orgSlug ? setRepoNameAction(projectId) : setOrgSlugAction();
|
|
867
867
|
// gitvault-byo-primary-bucket task 3.5: a BYO vault's "add a copy" remedy
|
|
868
868
|
// names a SECOND customer-held location (D7) — the plain mirror hint
|
|
869
869
|
// frames the mirror as the FIRST custody-held copy, which is false once
|
|
@@ -872,7 +872,7 @@ async function printCreateResult({ sdk, projectId, vault, adopted, name, verbose
|
|
|
872
872
|
const mirrorAction = isByo
|
|
873
873
|
? nextAction("configure_mirror", { command: "run402 repos mirror <destination>", why: GITVAULT_BYO_UNMIRRORED_REMEDY_STATEMENT })
|
|
874
874
|
: nextAction("configure_mirror", { command: "run402 repos mirror <destination>", why: GITVAULT_MIRROR_SETUP_HINT });
|
|
875
|
-
const nextActions = [pushAction, ...remoteSkippedActions, mirrorAction,
|
|
875
|
+
const nextActions = [pushAction, ...remoteSkippedActions, mirrorAction, nameAction].filter(Boolean);
|
|
876
876
|
|
|
877
877
|
// Secret-bearing (recovery_receipt): built fresh every call, printed once,
|
|
878
878
|
// and never spilled into any cache path — see spillIfLarge's own doc
|
|
@@ -897,8 +897,8 @@ async function printCreateResult({ sdk, projectId, vault, adopted, name, verbose
|
|
|
897
897
|
(vault.deduplicated ? "already existed — nothing was re-allocated" : `allocated (genesis ${vault.genesis_sha256})`),
|
|
898
898
|
);
|
|
899
899
|
if (address) console.error(`address: ${address}`);
|
|
900
|
-
else if (!orgSlug) console.error("no named address yet —
|
|
901
|
-
else console.error(`no address
|
|
900
|
+
else if (!orgSlug) console.error("no named address yet — set an org slug (run402 org slug <slug>) to get run402::<slug>/<name> addresses");
|
|
901
|
+
else console.error(`no address set — run 'run402 repos rename <name> --project ${projectId}' to set one`);
|
|
902
902
|
if (remoteScaffolded) {
|
|
903
903
|
console.error(`remote '${vault.remote.name}' -> ${vault.remote.url} (${vault.remote.reason})`);
|
|
904
904
|
if (vault.remote.nested) console.error(`nested repository inside ${vault.remote.enclosing_toplevel}${vault.remote.excluded_in_enclosing ? " — excluded there via .git/info/exclude" : " — could not write its .git/info/exclude"}`);
|
|
@@ -918,7 +918,7 @@ async function printCreateResult({ sdk, projectId, vault, adopted, name, verbose
|
|
|
918
918
|
console.error(vault.terminal_loss_statement);
|
|
919
919
|
await printKeystoreLocation();
|
|
920
920
|
console.error("");
|
|
921
|
-
console.error("nothing was deployed — this is a vault-only repo. Deploy later with `run402 deploy
|
|
921
|
+
console.error("nothing was deployed — this is a vault-only repo. Deploy later with `run402 deploy`, or never.");
|
|
922
922
|
printVerboseStats(verboseArgv, sdk);
|
|
923
923
|
}
|
|
924
924
|
|
|
@@ -955,13 +955,13 @@ async function createProvision(name, dir, a) {
|
|
|
955
955
|
// with the old project id.
|
|
956
956
|
const idempotencyKey = flagValue(a, "--idempotency-key") ?? `repos-create:${orgId ?? "org-of-one"}:${name}`;
|
|
957
957
|
|
|
958
|
-
// A genuinely bare machine has no
|
|
958
|
+
// A genuinely bare machine has no local wallet file at all, and the NO_WALLET
|
|
959
959
|
// precheck below would refuse before the provision call could ever answer
|
|
960
960
|
// NO_ACTIVE_TIER, so the cold-start fold would never reach the one case it
|
|
961
961
|
// exists for. Fold first when there is no wallet; `--no-init` keeps the
|
|
962
962
|
// bare refusal.
|
|
963
|
-
if (!isCoreApiTarget() && !loadLiveControlPlaneSession() && !
|
|
964
|
-
console.error("no wallet on this machine — folding the cold-start chain (
|
|
963
|
+
if (!isCoreApiTarget() && !loadLiveControlPlaneSession() && !readWallet() && !a.includes("--no-init")) {
|
|
964
|
+
console.error("no wallet on this machine — folding the cold-start chain (wallet -> faucet -> prototype tier)");
|
|
965
965
|
try {
|
|
966
966
|
const { foldColdStartChain } = await import("./cold-start.mjs");
|
|
967
967
|
await foldColdStartChain((line) => console.error(` ${line}`));
|
|
@@ -970,7 +970,7 @@ async function createProvision(name, dir, a) {
|
|
|
970
970
|
return;
|
|
971
971
|
}
|
|
972
972
|
}
|
|
973
|
-
if (!isCoreApiTarget() && !loadLiveControlPlaneSession())
|
|
973
|
+
if (!isCoreApiTarget() && !loadLiveControlPlaneSession()) walletAuthHeaders("/projects/v1");
|
|
974
974
|
|
|
975
975
|
const provisionOnce = () =>
|
|
976
976
|
withAutoApprove(() => sdk.projects.provision({ tier, name, ...(orgId ? { orgId } : {}), idempotencyKey }));
|
|
@@ -980,12 +980,12 @@ async function createProvision(name, dir, a) {
|
|
|
980
980
|
provisioned = await provisionOnce();
|
|
981
981
|
} catch (err) {
|
|
982
982
|
// kygit-handoff design D5: `repos create` on a fresh wallet folds the
|
|
983
|
-
// cold-start chain ONCE —
|
|
983
|
+
// cold-start chain ONCE — wallet → faucet → one x402 prototype
|
|
984
984
|
// payment, announced — then retries exactly once. `--no-init` opts
|
|
985
985
|
// out (the caller wants the bare NO_ACTIVE_TIER refusal).
|
|
986
986
|
const code = err?.body?.code ?? err?.code;
|
|
987
987
|
if (code === "NO_ACTIVE_TIER" && !a.includes("--no-init")) {
|
|
988
|
-
console.error("no active tier — folding the cold-start chain (
|
|
988
|
+
console.error("no active tier — folding the cold-start chain (wallet -> faucet -> prototype tier)");
|
|
989
989
|
try {
|
|
990
990
|
const { foldColdStartChain } = await import("./cold-start.mjs");
|
|
991
991
|
await foldColdStartChain((line) => console.error(` ${line}`));
|
|
@@ -1159,7 +1159,7 @@ async function list(args) {
|
|
|
1159
1159
|
}
|
|
1160
1160
|
printJson(sdk, { org_id: orgId, org_slug: orgSlug, repos });
|
|
1161
1161
|
console.error(`${repos.length} vault-bearing project(s) in this organization${usedFallback ? " (per-project fallback read — the bulk vaults-by-org route is not live on this gateway yet)" : ""}`);
|
|
1162
|
-
if (orgSlug) console.error(`org slug: ${orgSlug} — a repo with
|
|
1162
|
+
if (orgSlug) console.error(`org slug: ${orgSlug} — a repo with an address-form name set is reachable at run402::${orgSlug}/<name>`);
|
|
1163
1163
|
printVerboseStats(a, sdk);
|
|
1164
1164
|
}
|
|
1165
1165
|
|
|
@@ -1288,16 +1288,16 @@ async function rename(args) {
|
|
|
1288
1288
|
const orgSlug = owningOrg ? (await sdk.org(owningOrg).get()).slug : null;
|
|
1289
1289
|
if (orgSlug) address = gitvaultRemoteUrlForRepo(orgSlug, result.repo_name);
|
|
1290
1290
|
} catch {
|
|
1291
|
-
// The
|
|
1291
|
+
// The name is already set — a failed address-preview lookup is never fatal.
|
|
1292
1292
|
}
|
|
1293
1293
|
printJson(sdk, { ...result, address });
|
|
1294
1294
|
console.error(
|
|
1295
1295
|
result.previous_repo_name && result.previous_repo_name !== result.repo_name
|
|
1296
1296
|
? `renamed from "${result.previous_repo_name}" to "${result.repo_name}"`
|
|
1297
|
-
: `name "${result.repo_name}"
|
|
1297
|
+
: `name "${result.repo_name}" set for ${projectId}`,
|
|
1298
1298
|
);
|
|
1299
1299
|
if (address) console.error(`address: ${address}`);
|
|
1300
|
-
else console.error("this org has no slug yet —
|
|
1300
|
+
else console.error("this org has no slug yet — set one with `run402 org slug <slug>` to get a full run402::<slug>/<name> address");
|
|
1301
1301
|
printVerboseStats(a, sdk);
|
|
1302
1302
|
} catch (err) {
|
|
1303
1303
|
reportSdkError(err);
|
|
@@ -1726,7 +1726,7 @@ async function readInviteNoteInput(a) {
|
|
|
1726
1726
|
return parseInviteNoteJson(text, "stdin");
|
|
1727
1727
|
}
|
|
1728
1728
|
|
|
1729
|
-
/** Shared body for `parseHandoffNoteJson`/`parseInviteNoteJson` — `schema`/`kindLabel` name the
|
|
1729
|
+
/** Shared body for `parseHandoffNoteJson`/`parseInviteNoteJson` — `schema`/`kindLabel` name the redeem kind's own vocabulary. */
|
|
1730
1730
|
function parseClaimNoteJson(text, source, schema, kindLabel, helpCommand) {
|
|
1731
1731
|
let parsed;
|
|
1732
1732
|
try {
|
|
@@ -1817,7 +1817,7 @@ async function handoff(args) {
|
|
|
1817
1817
|
// gitvault-multi-writer (rev 47) task 6.4 — a handoff is now also a
|
|
1818
1818
|
// WRITER admission, not just a checkout pass: the recipient signs its
|
|
1819
1819
|
// own future pushes with a NEW key this vault's chain recognizes as a
|
|
1820
|
-
// writer the moment `resume`
|
|
1820
|
+
// writer the moment `resume` redeems it (design D4 — a grant minted here,
|
|
1821
1821
|
// a two-signature acceptance the recipient's own resume completes).
|
|
1822
1822
|
console.error(`the recipient becomes a WRITER on this vault the moment they resume — their own key signs future pushes, not yours.`);
|
|
1823
1823
|
console.error(`recipient runs: kygit resume <key printed below>`);
|
|
@@ -1837,13 +1837,13 @@ async function handoff(args) {
|
|
|
1837
1837
|
|
|
1838
1838
|
/**
|
|
1839
1839
|
* Whether this wallet needs the cold-start chain before a resume: no
|
|
1840
|
-
*
|
|
1840
|
+
* wallet file yet (a fresh machine — the viral case), or a wallet
|
|
1841
1841
|
* whose org holds no active tier. An unreachable tier status reads as
|
|
1842
|
-
* "no" — the
|
|
1842
|
+
* "no" — the redemption needs no tier, and a resume must never wait on a status
|
|
1843
1843
|
* read.
|
|
1844
1844
|
*/
|
|
1845
1845
|
async function resumeNeedsColdStart(sdk) {
|
|
1846
|
-
if (!
|
|
1846
|
+
if (!readWallet()) return true;
|
|
1847
1847
|
try {
|
|
1848
1848
|
const status = await sdk.tier.status();
|
|
1849
1849
|
return status?.active === false;
|
|
@@ -1856,11 +1856,11 @@ async function resumeNeedsColdStart(sdk) {
|
|
|
1856
1856
|
* `resume`'s cold-start fold: the SAME chain `create` runs on
|
|
1857
1857
|
* NO_ACTIVE_TIER (`cold-start.mjs`), announced step by step on stderr.
|
|
1858
1858
|
* Never throws — a failure is returned as `{ error, next_action }` so the
|
|
1859
|
-
* caller carries it in the result and proceeds with the
|
|
1859
|
+
* caller carries it in the result and proceeds with the redemption.
|
|
1860
1860
|
*/
|
|
1861
1861
|
async function foldColdStartForResume(sdk) {
|
|
1862
1862
|
if (!(await resumeNeedsColdStart(sdk))) return { performed: false, skipped: "tier_active" };
|
|
1863
|
-
console.error("no active tier — folding the cold-start chain (
|
|
1863
|
+
console.error("no active tier — folding the cold-start chain (wallet -> faucet -> prototype tier) before the redemption");
|
|
1864
1864
|
try {
|
|
1865
1865
|
const { foldColdStartChain } = await import("./cold-start.mjs");
|
|
1866
1866
|
const chain = await foldColdStartChain((line) => console.error(` ${line}`));
|
|
@@ -1868,16 +1868,16 @@ async function foldColdStartForResume(sdk) {
|
|
|
1868
1868
|
} catch (err) {
|
|
1869
1869
|
const code = err?.body?.code ?? err?.code ?? null;
|
|
1870
1870
|
const message = err?.body?.message ?? err?.message ?? String(err);
|
|
1871
|
-
console.error(`cold-start chain failed (${code ?? "error"}: ${message}) — continuing with the
|
|
1871
|
+
console.error(`cold-start chain failed (${code ?? "error"}: ${message}) — continuing with the redemption; run \`run402 tier set prototype\` afterwards`);
|
|
1872
1872
|
return {
|
|
1873
1873
|
performed: false,
|
|
1874
1874
|
error: { code, message },
|
|
1875
|
-
next_action: { type: "renew_tier", command: "run402 tier set prototype", why: "The resume proceeded without a tier of your own; the
|
|
1875
|
+
next_action: { type: "renew_tier", command: "run402 tier set prototype", why: "The resume proceeded without a tier of your own; the free prototype tier is what lets this wallet create and deploy projects." },
|
|
1876
1876
|
};
|
|
1877
1877
|
}
|
|
1878
1878
|
}
|
|
1879
1879
|
|
|
1880
|
-
/** `kygit.handoff-note.v1` / `kygit.invite-note.v1` rendered as Markdown — shared body, `title` names the
|
|
1880
|
+
/** `kygit.handoff-note.v1` / `kygit.invite-note.v1` rendered as Markdown — shared body, `title` names the redeem kind ("Handoff" or "Invite"). */
|
|
1881
1881
|
function renderClaimNoteMarkdown(note, title) {
|
|
1882
1882
|
if (!note) return null;
|
|
1883
1883
|
const lines = [];
|
|
@@ -1939,12 +1939,12 @@ async function resume(args) {
|
|
|
1939
1939
|
}
|
|
1940
1940
|
// A resumed agent is a NEW run402 wallet, and the loop is the
|
|
1941
1941
|
// point — so on a wallet with no active tier `resume` folds the same
|
|
1942
|
-
// cold-start chain `create` does (
|
|
1943
|
-
// prototype payment, announced) BEFORE the
|
|
1942
|
+
// cold-start chain `create` does (wallet → faucet → one x402
|
|
1943
|
+
// prototype payment, announced) BEFORE the redemption. The redemption itself needs
|
|
1944
1944
|
// no tier, so the chain is never allowed to block a resume: a faucet
|
|
1945
1945
|
// throttle or payment failure is reported on stderr, carried in the
|
|
1946
1946
|
// result as `cold_start.error` with a `renew_tier` next action, and the
|
|
1947
|
-
//
|
|
1947
|
+
// redemption proceeds (the SDK still creates the bare wallet it needs).
|
|
1948
1948
|
// `--no-init` opts out entirely.
|
|
1949
1949
|
const coldStart = a.includes("--no-init") ? { performed: false, skipped: "no_init" } : await foldColdStartForResume(sdk);
|
|
1950
1950
|
try {
|
|
@@ -1956,7 +1956,7 @@ async function resume(args) {
|
|
|
1956
1956
|
const { remoteHelperNextAction } = await import("./path-lookup.mjs");
|
|
1957
1957
|
const helperAction = result.restored?.dir ? remoteHelperNextAction(result.restored.dir) : null;
|
|
1958
1958
|
if (helperAction) result.next_actions = [...(result.next_actions ?? []), helperAction];
|
|
1959
|
-
} catch { /* never fails a completed
|
|
1959
|
+
} catch { /* never fails a completed redemption */ }
|
|
1960
1960
|
if (a.includes("--json")) {
|
|
1961
1961
|
printJson(sdk, { ...result, cold_start: coldStart });
|
|
1962
1962
|
} else {
|
|
@@ -1973,7 +1973,7 @@ async function resume(args) {
|
|
|
1973
1973
|
if (result.writer_activation) {
|
|
1974
1974
|
console.error(`writer: ${result.writer_activation.outcome} (generation ${result.writer_activation.generation})`);
|
|
1975
1975
|
}
|
|
1976
|
-
if (result.deduplicated) console.error("note: this key was already
|
|
1976
|
+
if (result.deduplicated) console.error("note: this key was already redeemed by this same principal — the ORIGINAL envelope was reused (safe replay)");
|
|
1977
1977
|
for (const na of result.next_actions ?? []) {
|
|
1978
1978
|
if (na.command) console.error(`next: ${na.command}${na.why ? ` — ${na.why}` : ""}`);
|
|
1979
1979
|
}
|
|
@@ -2067,15 +2067,15 @@ async function invite(args) {
|
|
|
2067
2067
|
console.error(`invite minted: role ${result.minted_role}, expires ${result.expires_at}, room ${result.room?.room_key ?? "(unknown)"}`);
|
|
2068
2068
|
console.error(`recipient runs: kygit join <key printed below>`);
|
|
2069
2069
|
if (result.inviter_presence && result.inviter_presence.registered === false) {
|
|
2070
|
-
console.error(`note: your own presence was not registered (${result.inviter_presence.error}) — the invite still mints and
|
|
2070
|
+
console.error(`note: your own presence was not registered (${result.inviter_presence.error}) — the invite still mints and can be redeemed`);
|
|
2071
2071
|
}
|
|
2072
|
-
if (result.
|
|
2073
|
-
console.error(`note: the room
|
|
2072
|
+
if (result.room_message && result.room_message.posted === false) {
|
|
2073
|
+
console.error(`note: the room message was not posted (${result.room_message.reason}) — the invite still mints and can still be redeemed`);
|
|
2074
2074
|
}
|
|
2075
|
-
// The inviter's own
|
|
2075
|
+
// The inviter's own message must not wake the inviter's next `messages wait`:
|
|
2076
2076
|
// advance this checkout's stored cursor past it (best-effort).
|
|
2077
|
-
if (result.room?.room_key && result.
|
|
2078
|
-
try { updateRoomState(result.room.organization_id, result.room.room_key, { cursor: result.
|
|
2077
|
+
if (result.room?.room_key && result.room_message?.posted && typeof result.room_message.cursor === "string") {
|
|
2078
|
+
try { updateRoomState(result.room.organization_id, result.room.room_key, { cursor: result.room_message.cursor }); } catch { /* never fails a mint */ }
|
|
2079
2079
|
}
|
|
2080
2080
|
if (asJson) {
|
|
2081
2081
|
printJson(sdk, result);
|
|
@@ -2093,7 +2093,7 @@ async function invite(args) {
|
|
|
2093
2093
|
|
|
2094
2094
|
/**
|
|
2095
2095
|
* `run402 repos join` — the full cold-start chain (SAME fold `resume`
|
|
2096
|
-
* uses),
|
|
2096
|
+
* uses), redeem, restore exactly as `resume` does, pin `r402.room` to the
|
|
2097
2097
|
* invite's OWN room, register this session's presence, post ONE arrival
|
|
2098
2098
|
* fact, and report the inviter by name and labels, live presences, the
|
|
2099
2099
|
* catch-up cursor, and the last few messages (kygit-invite design D5).
|
|
@@ -2111,9 +2111,9 @@ async function joinInvite(args) {
|
|
|
2111
2111
|
if (!key) fail({ code: "BAD_USAGE", message: "Missing the Invite Key on stdin.", hint: "Pipe the kgi1_… key, or pass it as a positional argument." });
|
|
2112
2112
|
}
|
|
2113
2113
|
// kygit-invite design D5: a joined agent is a NEW run402 wallet, so `join`
|
|
2114
|
-
// folds the SAME cold-start chain `resume` does (
|
|
2115
|
-
// x402 prototype payment, announced) BEFORE the
|
|
2116
|
-
// needs no tier, so the chain never blocks the
|
|
2114
|
+
// folds the SAME cold-start chain `resume` does (wallet → faucet → one
|
|
2115
|
+
// x402 prototype payment, announced) BEFORE the redemption; the redemption itself
|
|
2116
|
+
// needs no tier, so the chain never blocks the redemption. `--no-init` opts
|
|
2117
2117
|
// out entirely.
|
|
2118
2118
|
const coldStart = a.includes("--no-init") ? { performed: false, skipped: "no_init" } : await foldColdStartForResume(sdk);
|
|
2119
2119
|
const { program, model } = resolveHarnessLabels();
|
|
@@ -2156,7 +2156,7 @@ async function joinInvite(args) {
|
|
|
2156
2156
|
const { remoteHelperNextAction } = await import("./path-lookup.mjs");
|
|
2157
2157
|
const helperAction = result.restored?.dir ? remoteHelperNextAction(result.restored.dir) : null;
|
|
2158
2158
|
if (helperAction) result.next_actions = [...(result.next_actions ?? []), helperAction];
|
|
2159
|
-
} catch { /* never fails a completed
|
|
2159
|
+
} catch { /* never fails a completed redemption */ }
|
|
2160
2160
|
if (a.includes("--json")) {
|
|
2161
2161
|
printJson(sdk, { ...result, cold_start: coldStart });
|
|
2162
2162
|
} else {
|
|
@@ -2166,7 +2166,7 @@ async function joinInvite(args) {
|
|
|
2166
2166
|
}
|
|
2167
2167
|
console.error("");
|
|
2168
2168
|
console.error(`joined into ${result.restored.dir} (branch ${result.restored.branch})`);
|
|
2169
|
-
if (result.deduplicated) console.error("note: this key was already
|
|
2169
|
+
if (result.deduplicated) console.error("note: this key was already redeemed by this same principal — the ORIGINAL envelope was reused (safe replay)");
|
|
2170
2170
|
// gitvault-multi-writer (rev 47) / kygit-invite design D5 — this
|
|
2171
2171
|
// checkout's own writer activation, printed in the SAME `writer: …`
|
|
2172
2172
|
// shape `resume` uses. `pending` is D9's not-stranded path: the key is
|
|
@@ -2591,8 +2591,8 @@ async function fsck(args) {
|
|
|
2591
2591
|
const GC_VALUE_FLAGS = [...COMMON_VALUE_FLAGS, "--intent-core", "--verifier-receipt"];
|
|
2592
2592
|
|
|
2593
2593
|
/**
|
|
2594
|
-
* One line of headroom disclosure. Printed whether or not things fit:
|
|
2595
|
-
*
|
|
2594
|
+
* One line of headroom disclosure. Printed whether or not things fit: a
|
|
2595
|
+
* person deciding when to compact wants the numbers in the passing case too
|
|
2596
2596
|
* (gitvault-compaction-headroom-preflight D4).
|
|
2597
2597
|
*/
|
|
2598
2598
|
function printHeadroomNote(headroom) {
|
|
@@ -2767,7 +2767,7 @@ async function accessRead(args) {
|
|
|
2767
2767
|
const cp = loadLiveControlPlaneSession();
|
|
2768
2768
|
if (cp) {
|
|
2769
2769
|
try {
|
|
2770
|
-
const mine = await sdk.
|
|
2770
|
+
const mine = await sdk.session.sourceAccessWrappers({ token: cp.control_plane_session_token });
|
|
2771
2771
|
result.member_custody = mine.encryption_key
|
|
2772
2772
|
? {
|
|
2773
2773
|
available: true,
|
|
@@ -2782,7 +2782,7 @@ async function accessRead(args) {
|
|
|
2782
2782
|
result.member_custody = { available: false, reason: e?.code ?? "read_failed", hint: "your own wrapper custody could not be read (older gateway, or the session lacks it)." };
|
|
2783
2783
|
}
|
|
2784
2784
|
} else {
|
|
2785
|
-
result.member_custody = { available: false, reason: "no_control_plane_session", hint: "run 'run402
|
|
2785
|
+
result.member_custody = { available: false, reason: "no_control_plane_session", hint: "run 'run402 login' to include your own wrapper custody here." };
|
|
2786
2786
|
}
|
|
2787
2787
|
if (human) {
|
|
2788
2788
|
console.log(formatAccessHuman(result));
|
|
@@ -3172,7 +3172,7 @@ async function recover(args) {
|
|
|
3172
3172
|
*
|
|
3173
3173
|
* Principal-scoped, not repo-scoped (one bundle covers every vault you are
|
|
3174
3174
|
* a recipient of) — which is why the auth is your control-plane (human)
|
|
3175
|
-
* session (`run402
|
|
3175
|
+
* session (`run402 login`), not the wallet. Without a
|
|
3176
3176
|
* session the request falls back to the active WALLET's agent principal,
|
|
3177
3177
|
* which normally holds no wrappers — truthful, with a stderr note saying so.
|
|
3178
3178
|
* Enrollment/activation/revocation are browser ceremonies at
|
|
@@ -3182,7 +3182,7 @@ function sourceAccessTokenOpts(commandLabel) {
|
|
|
3182
3182
|
const cp = loadLiveControlPlaneSession();
|
|
3183
3183
|
if (!cp) {
|
|
3184
3184
|
console.error(
|
|
3185
|
-
`no control-plane (human) session — ${commandLabel} will answer for the active WALLET's agent principal, which normally holds no wrappers. Run 'run402
|
|
3185
|
+
`no control-plane (human) session — ${commandLabel} will answer for the active WALLET's agent principal, which normally holds no wrappers. Run 'run402 login' to act as yourself.`,
|
|
3186
3186
|
);
|
|
3187
3187
|
return {};
|
|
3188
3188
|
}
|
|
@@ -3196,7 +3196,7 @@ async function recoveryBundle(args) {
|
|
|
3196
3196
|
const out = flagValue(a, "--out");
|
|
3197
3197
|
const sdk = getSdk();
|
|
3198
3198
|
try {
|
|
3199
|
-
const bundle = await sdk.
|
|
3199
|
+
const bundle = await sdk.session.sourceAccessRecoveryBundle(sourceAccessTokenOpts("recovery-bundle"));
|
|
3200
3200
|
// Full JSON to stdout regardless — the pipe contract is sacred; the file
|
|
3201
3201
|
// is the keep-a-copy convenience (0600 — the bundle is ciphertext the
|
|
3202
3202
|
// platform cannot open, but it is still half of a recovery credential).
|