run402 4.95.0 → 4.96.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 +3 -3
- package/cli.mjs +1 -21
- package/core-dist/keystore.js +1 -1
- package/git-remote-run402.mjs +6 -6
- package/lib/cold-start.mjs +2 -2
- package/lib/command-manifest.mjs +3 -41
- package/lib/credentials.mjs +1 -1
- package/lib/daemon-path.mjs +3 -3
- package/lib/deploy-v2.mjs +17 -17
- package/lib/doctor.mjs +45 -54
- package/lib/init.mjs +29 -29
- package/lib/next-actions.mjs +1 -1
- package/lib/org-context.mjs +9 -9
- package/lib/orgs.mjs +19 -19
- package/lib/path-lookup.mjs +7 -10
- package/lib/path-lookup.test.mjs +19 -21
- package/lib/remote-helper-session.mjs +93 -93
- package/lib/repos.mjs +174 -175
- package/lib/rooms-context.mjs +7 -7
- package/lib/up.mjs +14 -14
- package/lib/{gitvault-capabilities.mjs → vault-capabilities.mjs} +10 -14
- package/lib/{gitvault-daemon-run.mjs → vault-daemon-run.mjs} +2 -2
- package/lib/{gitvault-daemon.mjs → vault-daemon.mjs} +23 -23
- package/lib/{gitvault-scaffold.mjs → vault-scaffold.mjs} +12 -12
- package/lib/{gitvault-target.mjs → vault-target.mjs} +22 -17
- package/package.json +2 -2
- package/sdk/core-dist/keystore.js +1 -1
- package/sdk/dist/errors.d.ts +4 -4
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/index.d.ts +9 -9
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +8 -8
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/namespaces/deploy.d.ts +5 -5
- package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.js +20 -20
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +17 -17
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/org.d.ts +2 -2
- package/sdk/dist/namespaces/org.js +2 -2
- package/sdk/dist/namespaces/org.types.d.ts +3 -3
- package/sdk/dist/namespaces/pay.js +1 -1
- package/sdk/dist/namespaces/{gitvault.d.ts → repos.d.ts} +436 -449
- package/sdk/dist/namespaces/repos.d.ts.map +1 -0
- package/sdk/dist/namespaces/{gitvault.js → repos.js} +451 -459
- package/sdk/dist/namespaces/repos.js.map +1 -0
- package/sdk/dist/namespaces/rooms.js +2 -2
- package/sdk/dist/namespaces/rooms.js.map +1 -1
- package/sdk/dist/namespaces/session.d.ts +2 -2
- package/sdk/dist/namespaces/session.d.ts.map +1 -1
- package/sdk/dist/namespaces/session.js +2 -2
- package/sdk/dist/namespaces/session.js.map +1 -1
- package/sdk/dist/namespaces/tier.d.ts +3 -3
- package/sdk/dist/namespaces/tier.d.ts.map +1 -1
- package/sdk/dist/namespaces/{gitvault.crypto.d.ts → vault.crypto.d.ts} +141 -141
- package/sdk/dist/namespaces/vault.crypto.d.ts.map +1 -0
- package/sdk/dist/namespaces/{gitvault.crypto.js → vault.crypto.js} +173 -173
- package/sdk/dist/namespaces/vault.crypto.js.map +1 -0
- package/sdk/dist/namespaces/{gitvault.types.d.ts → vault.types.d.ts} +136 -136
- package/sdk/dist/namespaces/vault.types.d.ts.map +1 -0
- package/sdk/dist/namespaces/{gitvault.types.js → vault.types.js} +4 -4
- package/sdk/dist/namespaces/vault.types.js.map +1 -0
- package/sdk/dist/node/bearer-redeem-key.d.ts +1 -1
- package/sdk/dist/node/bearer-redeem-key.js +5 -5
- package/sdk/dist/node/bearer-redeem-key.js.map +1 -1
- package/sdk/dist/node/http-dispatcher.js +5 -5
- package/sdk/dist/node/http-dispatcher.js.map +1 -1
- package/sdk/dist/node/index.d.ts +29 -29
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +39 -39
- package/sdk/dist/node/index.js.map +1 -1
- package/sdk/dist/node/{gitvault-address.d.ts → vault-address.d.ts} +42 -42
- package/sdk/dist/node/vault-address.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-address.js → vault-address.js} +43 -43
- package/sdk/dist/node/vault-address.js.map +1 -0
- package/sdk/dist/node/{gitvault-apply.d.ts → vault-apply.d.ts} +27 -27
- package/sdk/dist/node/vault-apply.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-apply.js → vault-apply.js} +38 -38
- package/sdk/dist/node/vault-apply.js.map +1 -0
- package/sdk/dist/node/vault-byo-config.d.ts +29 -0
- package/sdk/dist/node/vault-byo-config.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-byo-config.js → vault-byo-config.js} +18 -18
- package/sdk/dist/node/vault-byo-config.js.map +1 -0
- package/sdk/dist/node/vault-byo-probe.d.ts +20 -0
- package/sdk/dist/node/vault-byo-probe.d.ts.map +1 -0
- package/sdk/dist/node/vault-byo-probe.js +57 -0
- package/sdk/dist/node/vault-byo-probe.js.map +1 -0
- package/sdk/dist/node/{gitvault-creation-journal.d.ts → vault-creation-journal.d.ts} +69 -69
- package/sdk/dist/node/vault-creation-journal.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-creation-journal.js → vault-creation-journal.js} +54 -54
- package/sdk/dist/node/vault-creation-journal.js.map +1 -0
- package/sdk/dist/node/{gitvault-degraded-read.d.ts → vault-degraded-read.d.ts} +34 -34
- package/sdk/dist/node/vault-degraded-read.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-degraded-read.js → vault-degraded-read.js} +24 -24
- package/sdk/dist/node/vault-degraded-read.js.map +1 -0
- package/sdk/dist/node/{gitvault-deploy.d.ts → vault-deploy.d.ts} +67 -67
- package/sdk/dist/node/vault-deploy.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-deploy.js → vault-deploy.js} +27 -27
- package/sdk/dist/node/vault-deploy.js.map +1 -0
- package/sdk/dist/node/{gitvault-edge-fetch.d.ts → vault-edge-fetch.d.ts} +9 -9
- package/sdk/dist/node/vault-edge-fetch.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-edge-fetch.js → vault-edge-fetch.js} +11 -11
- package/sdk/dist/node/vault-edge-fetch.js.map +1 -0
- package/sdk/dist/node/{gitvault-handoff.d.ts → vault-handoff.d.ts} +9 -9
- package/sdk/dist/node/vault-handoff.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-handoff.js → vault-handoff.js} +24 -24
- package/sdk/dist/node/vault-handoff.js.map +1 -0
- package/sdk/dist/node/{gitvault-keystore.d.ts → vault-keystore.d.ts} +87 -77
- package/sdk/dist/node/vault-keystore.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-keystore.js → vault-keystore.js} +105 -68
- package/sdk/dist/node/vault-keystore.js.map +1 -0
- package/sdk/dist/node/{gitvault-member-bundle.d.ts → vault-member-bundle.d.ts} +17 -17
- package/sdk/dist/node/vault-member-bundle.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-member-bundle.js → vault-member-bundle.js} +11 -11
- package/sdk/dist/node/vault-member-bundle.js.map +1 -0
- package/sdk/dist/node/{gitvault-mirror-backend.d.ts → vault-mirror-backend.d.ts} +26 -26
- package/sdk/dist/node/vault-mirror-backend.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-mirror-backend.js → vault-mirror-backend.js} +25 -25
- package/sdk/dist/node/vault-mirror-backend.js.map +1 -0
- package/sdk/dist/node/{gitvault-mirror-config.d.ts → vault-mirror-config.d.ts} +23 -23
- package/sdk/dist/node/vault-mirror-config.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-mirror-config.js → vault-mirror-config.js} +16 -16
- package/sdk/dist/node/vault-mirror-config.js.map +1 -0
- package/sdk/dist/node/{gitvault-mirror.d.ts → vault-mirror.d.ts} +36 -36
- package/sdk/dist/node/vault-mirror.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-mirror.js → vault-mirror.js} +75 -75
- package/sdk/dist/node/vault-mirror.js.map +1 -0
- package/sdk/dist/node/{gitvault-native-crypto.d.ts → vault-native-crypto.d.ts} +10 -10
- package/sdk/dist/node/vault-native-crypto.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-native-crypto.js → vault-native-crypto.js} +16 -16
- package/sdk/dist/node/vault-native-crypto.js.map +1 -0
- package/sdk/dist/node/{gitvault-open-or-create.d.ts → vault-open-or-create.d.ts} +16 -16
- package/sdk/dist/node/vault-open-or-create.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-open-or-create.js → vault-open-or-create.js} +10 -10
- package/sdk/dist/node/vault-open-or-create.js.map +1 -0
- package/sdk/dist/node/{gitvault-prewarm.d.ts → vault-prewarm.d.ts} +13 -13
- package/sdk/dist/node/vault-prewarm.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-prewarm.js → vault-prewarm.js} +25 -25
- package/sdk/dist/node/vault-prewarm.js.map +1 -0
- package/sdk/dist/node/{gitvault-profile-scan.d.ts → vault-profile-scan.d.ts} +3 -3
- package/sdk/dist/node/vault-profile-scan.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-profile-scan.js → vault-profile-scan.js} +12 -12
- package/sdk/dist/node/vault-profile-scan.js.map +1 -0
- package/sdk/dist/node/{gitvault-prune.d.ts → vault-prune.d.ts} +61 -61
- package/sdk/dist/node/vault-prune.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-prune.js → vault-prune.js} +34 -34
- package/sdk/dist/node/vault-prune.js.map +1 -0
- package/sdk/dist/node/{gitvault-publication.d.ts → vault-publication.d.ts} +399 -399
- package/sdk/dist/node/vault-publication.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-publication.js → vault-publication.js} +584 -584
- package/sdk/dist/node/vault-publication.js.map +1 -0
- package/sdk/dist/node/{gitvault-push-to-create.d.ts → vault-push-to-create.d.ts} +16 -16
- package/sdk/dist/node/vault-push-to-create.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-push-to-create.js → vault-push-to-create.js} +9 -9
- package/sdk/dist/node/vault-push-to-create.js.map +1 -0
- package/sdk/dist/node/{gitvault-recover.d.ts → vault-recover.d.ts} +50 -50
- package/sdk/dist/node/vault-recover.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-recover.js → vault-recover.js} +84 -84
- package/sdk/dist/node/vault-recover.js.map +1 -0
- package/sdk/dist/node/{gitvault-restore.d.ts → vault-restore.d.ts} +8 -8
- package/sdk/dist/node/vault-restore.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-restore.js → vault-restore.js} +11 -11
- package/sdk/dist/node/vault-restore.js.map +1 -0
- package/sdk/dist/node/{gitvault-snapshot.d.ts → vault-snapshot.d.ts} +48 -48
- package/sdk/dist/node/vault-snapshot.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-snapshot.js → vault-snapshot.js} +61 -61
- package/sdk/dist/node/vault-snapshot.js.map +1 -0
- package/sdk/dist/node/{gitvault-writer-state.d.ts → vault-writer-state.d.ts} +8 -8
- package/sdk/dist/node/vault-writer-state.d.ts.map +1 -0
- package/sdk/dist/node/{gitvault-writer-state.js → vault-writer-state.js} +15 -15
- package/sdk/dist/node/vault-writer-state.js.map +1 -0
- package/sdk/dist/node/workflow-output.js +4 -4
- package/sdk/dist/node/workflow-output.js.map +1 -1
- package/vault-surface.json +40 -0
- package/gitvault-surface.json +0 -89
- package/lib/gitvault.mjs +0 -163
- package/lib/source-access.mjs +0 -70
- package/sdk/dist/namespaces/gitvault.crypto.d.ts.map +0 -1
- package/sdk/dist/namespaces/gitvault.crypto.js.map +0 -1
- package/sdk/dist/namespaces/gitvault.d.ts.map +0 -1
- package/sdk/dist/namespaces/gitvault.js.map +0 -1
- package/sdk/dist/namespaces/gitvault.types.d.ts.map +0 -1
- package/sdk/dist/namespaces/gitvault.types.js.map +0 -1
- package/sdk/dist/node/gitvault-address.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-address.js.map +0 -1
- package/sdk/dist/node/gitvault-apply.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-apply.js.map +0 -1
- package/sdk/dist/node/gitvault-byo-config.d.ts +0 -29
- package/sdk/dist/node/gitvault-byo-config.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-byo-config.js.map +0 -1
- package/sdk/dist/node/gitvault-byo-probe.d.ts +0 -20
- package/sdk/dist/node/gitvault-byo-probe.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-byo-probe.js +0 -57
- package/sdk/dist/node/gitvault-byo-probe.js.map +0 -1
- package/sdk/dist/node/gitvault-creation-journal.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-creation-journal.js.map +0 -1
- package/sdk/dist/node/gitvault-degraded-read.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-degraded-read.js.map +0 -1
- package/sdk/dist/node/gitvault-deploy.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-deploy.js.map +0 -1
- package/sdk/dist/node/gitvault-edge-fetch.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-edge-fetch.js.map +0 -1
- package/sdk/dist/node/gitvault-handoff.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-handoff.js.map +0 -1
- package/sdk/dist/node/gitvault-keystore.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-keystore.js.map +0 -1
- package/sdk/dist/node/gitvault-member-bundle.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-member-bundle.js.map +0 -1
- package/sdk/dist/node/gitvault-mirror-backend.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-mirror-backend.js.map +0 -1
- package/sdk/dist/node/gitvault-mirror-config.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-mirror-config.js.map +0 -1
- package/sdk/dist/node/gitvault-mirror.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-mirror.js.map +0 -1
- package/sdk/dist/node/gitvault-native-crypto.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-native-crypto.js.map +0 -1
- package/sdk/dist/node/gitvault-open-or-create.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-open-or-create.js.map +0 -1
- package/sdk/dist/node/gitvault-prewarm.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-prewarm.js.map +0 -1
- package/sdk/dist/node/gitvault-profile-scan.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-profile-scan.js.map +0 -1
- package/sdk/dist/node/gitvault-prune.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-prune.js.map +0 -1
- package/sdk/dist/node/gitvault-publication.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-publication.js.map +0 -1
- package/sdk/dist/node/gitvault-push-to-create.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-push-to-create.js.map +0 -1
- package/sdk/dist/node/gitvault-recover.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-recover.js.map +0 -1
- package/sdk/dist/node/gitvault-restore.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-restore.js.map +0 -1
- package/sdk/dist/node/gitvault-snapshot.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-snapshot.js.map +0 -1
- package/sdk/dist/node/gitvault-writer-state.d.ts.map +0 -1
- package/sdk/dist/node/gitvault-writer-state.js.map +0 -1
package/lib/doctor.mjs
CHANGED
|
@@ -13,9 +13,9 @@ import { resolveApplicationScope, loadApplicationScanInput, scanDeploymentSource
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { existsSync, statSync } from "node:fs";
|
|
16
|
-
import {
|
|
16
|
+
import { VAULT_BYO_NO_PAYLOAD_COPY_STATEMENT } from "#sdk";
|
|
17
17
|
import { configDir, readWallet, loadKeyStore } from "./config.mjs";
|
|
18
|
-
import {
|
|
18
|
+
import { resolveVaultTarget } from "./vault-target.mjs";
|
|
19
19
|
import { getSdk } from "./sdk.mjs";
|
|
20
20
|
import {
|
|
21
21
|
resolveScanRoot,
|
|
@@ -54,7 +54,7 @@ const DOCTOR_CHECK_NAMES = [
|
|
|
54
54
|
"account_health",
|
|
55
55
|
"runtime_staleness",
|
|
56
56
|
"recovery_posture",
|
|
57
|
-
"
|
|
57
|
+
"vault",
|
|
58
58
|
"source_scan",
|
|
59
59
|
];
|
|
60
60
|
|
|
@@ -91,7 +91,7 @@ Output:
|
|
|
91
91
|
api_reachable error, tier inactive / frozen / past_due /
|
|
92
92
|
dormant / missing / error, error-severity source_scan findings
|
|
93
93
|
advisory a warning that never stops a deploy: account_health,
|
|
94
|
-
recovery_posture,
|
|
94
|
+
recovery_posture, vault, runtime_staleness, cli_update gaps
|
|
95
95
|
info ok / skipped / unknown
|
|
96
96
|
Agents: branch on \`ok\`; read \`warnings[]\` (one entry per gap) for the
|
|
97
97
|
non-blocking gaps and \`blocking[]\` for what to fix when \`ok\` is false.
|
|
@@ -117,16 +117,16 @@ Options:
|
|
|
117
117
|
--dir D Select the application directory for deployment diagnostics.
|
|
118
118
|
--manifest P Explicitly select a manifest (executable configs are trusted code).
|
|
119
119
|
--scan-dir D Advanced arbitrary scan; does not claim deployment readiness
|
|
120
|
-
--project <project_id> Target THIS project's
|
|
120
|
+
--project <project_id> Target THIS project's vault check instead of the repo-standing
|
|
121
121
|
default (the 4.38.0 pin / run402 remote / RUN402_PROJECT_ID / active
|
|
122
|
-
project, in that order — see \`
|
|
123
|
-
|
|
122
|
+
project, in that order — see \`vault-target.mjs\`). Scoped to the
|
|
123
|
+
vault check only; every other check is wallet/machine-wide, not
|
|
124
124
|
per-project, and is unaffected by this flag. Composes with --only.
|
|
125
125
|
--only <check> Run ONLY the named check (repeatable — pass it more than once
|
|
126
126
|
to run several). Every other check, INCLUDING the monorepo
|
|
127
127
|
source-tree scan, is suppressed rather than merely hidden: a
|
|
128
128
|
skipped check's network/filesystem work never runs at all, so
|
|
129
|
-
\`doctor --only
|
|
129
|
+
\`doctor --only vault\` costs one vault read, not a
|
|
130
130
|
config/tier/account/scan sweep. An unknown check name is
|
|
131
131
|
BAD_USAGE listing the valid names below. Not used with --buzz
|
|
132
132
|
(buzz mode is its own separate, always-complete check set).
|
|
@@ -164,7 +164,7 @@ Checks performed:
|
|
|
164
164
|
the org's disaster backstops if the agent machine dies. Evidence
|
|
165
165
|
levels: "configured" is what the platform verified, never proof an
|
|
166
166
|
off-platform passkey or saved code still exists.
|
|
167
|
-
-
|
|
167
|
+
- vault: the active project's vault — activation policy, whether THIS
|
|
168
168
|
machine can produce the capture a 'required' policy demands, open
|
|
169
169
|
unvaulted-override journals, and where the keystore lives (back it up:
|
|
170
170
|
whole-keystore loss is terminal for vault history)
|
|
@@ -310,7 +310,7 @@ export async function run(sub, args = []) {
|
|
|
310
310
|
const skipScan = all.includes("--no-scan");
|
|
311
311
|
const scanDirArgIdx = all.indexOf("--scan-dir");
|
|
312
312
|
const scanDirOverride = scanDirArgIdx >= 0 ? all[scanDirArgIdx + 1] : null;
|
|
313
|
-
// Scoped to the
|
|
313
|
+
// Scoped to the vault check (see HELP): every other check is
|
|
314
314
|
// wallet/machine-wide, not per-project.
|
|
315
315
|
const projectOverride = flagValue(all, "--project");
|
|
316
316
|
|
|
@@ -650,7 +650,7 @@ export async function run(sub, args = []) {
|
|
|
650
650
|
}
|
|
651
651
|
}
|
|
652
652
|
|
|
653
|
-
// 6c. Org recovery posture (
|
|
653
|
+
// 6c. Org recovery posture (vault-recovery-custody). One entry per
|
|
654
654
|
// vault-owning org the caller can see; rides the same account-status
|
|
655
655
|
// read. Evidence levels, not guarantees: "configured" names what the
|
|
656
656
|
// platform VERIFIED — it can never observe whether an off-platform
|
|
@@ -661,11 +661,11 @@ export async function run(sub, args = []) {
|
|
|
661
661
|
if (wanted("recovery_posture")) {
|
|
662
662
|
const posture = status.recovery_posture;
|
|
663
663
|
if (!Array.isArray(posture)) {
|
|
664
|
-
// Gateway older than
|
|
664
|
+
// Gateway older than vault-recovery-custody doesn't surface it.
|
|
665
665
|
checks.push({
|
|
666
666
|
name: "recovery_posture",
|
|
667
667
|
status: "skipped",
|
|
668
|
-
...(verbose && { hint: "account status has no 'recovery_posture' block; requires a
|
|
668
|
+
...(verbose && { hint: "account status has no 'recovery_posture' block; requires a vault-recovery-custody gateway." }),
|
|
669
669
|
});
|
|
670
670
|
} else if (posture.length === 0) {
|
|
671
671
|
// No vault-owning org in the caller's view — nothing to lose, nothing to advise.
|
|
@@ -718,15 +718,15 @@ export async function run(sub, args = []) {
|
|
|
718
718
|
});
|
|
719
719
|
}
|
|
720
720
|
|
|
721
|
-
// 6c.
|
|
722
|
-
// even when `
|
|
721
|
+
// 6c. vault (add-vault). Doctor was completely silent about the vault
|
|
722
|
+
// even when `vault_policy: required` was the single thing that would break
|
|
723
723
|
// the project's next deploy (dogfood #1, finding D1) — and doctor is where a
|
|
724
724
|
// user looks when something is wrong. It also prints WHERE the keystore is:
|
|
725
725
|
// "whole-keystore loss is terminal" was stated three times across this
|
|
726
726
|
// surface while the directory to back up was stated nowhere (finding D2).
|
|
727
727
|
//
|
|
728
728
|
// Read-only and best-effort in every branch: no project, no vault, or a
|
|
729
|
-
// gateway that does not know
|
|
729
|
+
// gateway that does not know vault are all ordinary and report `skipped`
|
|
730
730
|
// or `ok`, never a doctor failure. A vault-only project that has never
|
|
731
731
|
// deployed is a first-class shape (protocol D183), so its mere absence of a
|
|
732
732
|
// deploy raises nothing.
|
|
@@ -734,12 +734,12 @@ export async function run(sub, args = []) {
|
|
|
734
734
|
// TARGETING: when cwd is a repository
|
|
735
735
|
// with its own pinned repo id or run402/origin remote, doctor checks THAT
|
|
736
736
|
// vault, not the profile's active project — the same pin > remote >
|
|
737
|
-
// RUN402_PROJECT_ID env > active-project order every other
|
|
738
|
-
// follows (`
|
|
739
|
-
// all of that (the resolver's own top tier), same as every other
|
|
737
|
+
// RUN402_PROJECT_ID env > active-project order every other vault verb
|
|
738
|
+
// follows (`vault-target.mjs`). An explicit `--project <project_id>` outranks
|
|
739
|
+
// all of that (the resolver's own top tier), same as every other vault
|
|
740
740
|
// verb's `--project`.
|
|
741
|
-
if (wanted("
|
|
742
|
-
//
|
|
741
|
+
if (wanted("vault")) {
|
|
742
|
+
// vault-persistent-helper: a bounded LOCAL probe of the resident
|
|
743
743
|
// helper engine — {running:false} is a fine answer, never a finding
|
|
744
744
|
// (the daemon is an accelerator, not a dependency).
|
|
745
745
|
const daemonInfo = await (async () => {
|
|
@@ -783,18 +783,18 @@ export async function run(sub, args = []) {
|
|
|
783
783
|
return { running: false };
|
|
784
784
|
}
|
|
785
785
|
})();
|
|
786
|
-
const target = await
|
|
786
|
+
const target = await resolveVaultTarget({ repoDir: process.cwd(), explicitProjectId: projectOverride ?? undefined });
|
|
787
787
|
const projectId = target.project_id ?? null;
|
|
788
788
|
const repoId = target.repo_id ?? null;
|
|
789
789
|
if (!projectId && !repoId) {
|
|
790
790
|
checks.push({
|
|
791
|
-
name: "
|
|
791
|
+
name: "vault",
|
|
792
792
|
status: "skipped",
|
|
793
793
|
...(verbose && { hint: "no active project — run 'run402 projects use <project_id>' to check its vault." }),
|
|
794
794
|
});
|
|
795
795
|
} else {
|
|
796
796
|
try {
|
|
797
|
-
const gv = await getSdk().
|
|
797
|
+
const gv = await getSdk().repos.status({
|
|
798
798
|
...(repoId ? { repo_id: repoId } : { project_id: projectId }),
|
|
799
799
|
repo_dir: process.cwd(),
|
|
800
800
|
});
|
|
@@ -802,11 +802,11 @@ export async function run(sub, args = []) {
|
|
|
802
802
|
project_id: gv.project_id ?? projectId,
|
|
803
803
|
repo_id: gv.repo_id,
|
|
804
804
|
vault: gv.vault === null ? null : "allocated",
|
|
805
|
-
//
|
|
805
|
+
// vault-byo-primary-bucket task 3.5 — absent-or-"managed" is
|
|
806
806
|
// byte-identical to before this fold for every non-BYO vault.
|
|
807
807
|
storage_profile: gv.vault?.storage_profile ?? null,
|
|
808
808
|
byo_destination: gv.vault?.byo_destination ?? null,
|
|
809
|
-
|
|
809
|
+
vault_policy: gv.vault_policy,
|
|
810
810
|
keystore_root: gv.keystore.root,
|
|
811
811
|
can_sign: gv.keystore.can_sign,
|
|
812
812
|
holds_repo_key: gv.keystore.holds_repo_key,
|
|
@@ -819,7 +819,7 @@ export async function run(sub, args = []) {
|
|
|
819
819
|
// to the durability sentence instead of the terminal-loss claim.
|
|
820
820
|
covering_recipients: gv.covering_recipients ?? null,
|
|
821
821
|
daemon: daemonInfo,
|
|
822
|
-
//
|
|
822
|
+
// vault-multi-writer (rev 47) task 6.2 — this machine's own
|
|
823
823
|
// standing on the vault's chain-verified writer set. `null` only
|
|
824
824
|
// when there is no vault at all (nothing to be a writer OF).
|
|
825
825
|
// `read_only_vault` takes priority over the caller's own standing
|
|
@@ -839,22 +839,22 @@ export async function run(sub, args = []) {
|
|
|
839
839
|
if (value.writer === "read_only_vault") {
|
|
840
840
|
gaps.push("this vault has lost its last writer (D228 read-only terminal) — it still serves reads, but no push can be admitted until a new writer is admitted through a recovery path");
|
|
841
841
|
} else if (value.writer === "pending") {
|
|
842
|
-
gaps.push("this machine's key is an eligible writer candidate but not yet admitted — run 'run402 repos access sync' if you already hold writer standing on this vault, or ask a current writer to run any
|
|
842
|
+
gaps.push("this machine's key is an eligible writer candidate but not yet admitted — run 'run402 repos access sync' if you already hold writer standing on this vault, or ask a current writer to run any vault operation");
|
|
843
843
|
} else if (value.writer === "not_admitted") {
|
|
844
|
-
gaps.push("this machine's key is not an active writer on this vault — a push from here is refused
|
|
844
|
+
gaps.push("this machine's key is not an active writer on this vault — a push from here is refused VAULT_WRITER_NOT_ADMITTED; ask a current writer to admit you (org membership at role developer+ and a published signing key make you eligible)");
|
|
845
845
|
}
|
|
846
846
|
// The one that actually breaks the next deploy: the project demands a
|
|
847
847
|
// vaulted capture and THIS machine cannot produce one.
|
|
848
|
-
if (gv.
|
|
848
|
+
if (gv.vault_policy === "required" && !gv.keystore.holds_repo_key) {
|
|
849
849
|
gaps.push(
|
|
850
|
-
"
|
|
850
|
+
"vault_policy is 'required' but this machine holds no key for the vault — a deploy from here is refused with VAULT_CLIENT_UPGRADE_REQUIRED. " +
|
|
851
851
|
"Run 'run402 repos create --project <project_id>' (idempotent; resolves to the existing repo), or 'run402 repos policy grandfathered --reason <why>' to un-gate the project.",
|
|
852
852
|
);
|
|
853
|
-
} else if (gv.
|
|
854
|
-
gaps.push("
|
|
853
|
+
} else if (gv.vault_policy === "required" && !gv.keystore.can_sign) {
|
|
854
|
+
gaps.push("vault_policy is 'required' and this keystore is read-only (no signing key) — it can verify but cannot publish the capture a deploy needs");
|
|
855
855
|
}
|
|
856
856
|
if (gv.pending_overrides > 0) {
|
|
857
|
-
gaps.push(`${gv.pending_overrides} unvaulted-override journal(s) are still open — run 'run402 repos
|
|
857
|
+
gaps.push(`${gv.pending_overrides} unvaulted-override journal(s) are still open — run 'run402 repos capture' to drain them`);
|
|
858
858
|
}
|
|
859
859
|
// `matches` is a TRI-STATE: `false` alone is
|
|
860
860
|
// a real mismatch. `null` (a slug-form remote not yet resolved on
|
|
@@ -863,20 +863,11 @@ export async function run(sub, args = []) {
|
|
|
863
863
|
if (gv.remote && gv.remote.matches === false) {
|
|
864
864
|
gaps.push(`the '${gv.remote.name}' git remote points at a different project than ${value.project_id} (${gv.remote.url})`);
|
|
865
865
|
}
|
|
866
|
-
// A `kygit::` remote with no
|
|
867
|
-
// `git-remote-kygit` helper on PATH means every push/clone/fetch
|
|
868
|
-
// in this checkout fails inside git with an opaque error.
|
|
869
|
-
if (gv.remote?.url?.startsWith("kygit::")) {
|
|
870
|
-
const { isExecutableOnPath } = await import("./path-lookup.mjs");
|
|
871
|
-
if (!isExecutableOnPath("git-remote-kygit")) {
|
|
872
|
-
gaps.push("this checkout's remote is kygit:: but git-remote-kygit is not on PATH — run `npm i -g @kychee/kygit`");
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
866
|
// Echoed exactly as the SDK reported them — including the
|
|
876
867
|
// doctor-persistent `grandfathered` advisory it owns.
|
|
877
868
|
for (const w of gv.warnings ?? []) gaps.push(`${w.kind}: ${w.message}`);
|
|
878
869
|
|
|
879
|
-
//
|
|
870
|
+
// vault-mirror-and-recover task 4.3 + vault-mirror-default:
|
|
880
871
|
// mirror currency, reported ALONGSIDE (never in place of) the
|
|
881
872
|
// deploy-related gaps above, and never blocking `run402 deploy`'s
|
|
882
873
|
// own gate — the vault lane's outcome is unaffected regardless of
|
|
@@ -885,14 +876,14 @@ export async function run(sub, args = []) {
|
|
|
885
876
|
// unreachable or vault unread). Only STALE is actionable enough to
|
|
886
877
|
// become a warning gap; a vault with no successful mirror copy yet
|
|
887
878
|
// carries the SDK-computed `vault_unmirrored` finding — named and
|
|
888
|
-
// standing (
|
|
879
|
+
// standing (vault-mirror-default supersedes the old anonymous
|
|
889
880
|
// `advisory` string), echoed verbatim, and deliberately NOT pushed
|
|
890
881
|
// into `gaps`: informational, never blocking, computed client-side
|
|
891
882
|
// only, cleared by the first successful mirror write or sync.
|
|
892
883
|
if (gv.vault !== null && value.repo_id) {
|
|
893
884
|
try {
|
|
894
|
-
const mirrorStatus = await getSdk().
|
|
895
|
-
value.
|
|
885
|
+
const mirrorStatus = await getSdk().repos.mirrorStatus({ repo_id: value.repo_id, is_byo: value.storage_profile === "byo" });
|
|
886
|
+
value.vault_mirror = {
|
|
896
887
|
configured: mirrorStatus.configured,
|
|
897
888
|
destination: mirrorStatus.destination,
|
|
898
889
|
mirrored_generation: mirrorStatus.mirrored_generation,
|
|
@@ -912,12 +903,12 @@ export async function run(sub, args = []) {
|
|
|
912
903
|
}
|
|
913
904
|
}
|
|
914
905
|
|
|
915
|
-
//
|
|
906
|
+
// vault-byo-primary-bucket task 3.5 — unconditional, independent
|
|
916
907
|
// of mirror status (D7); imported from the canonical constants, never
|
|
917
908
|
// paraphrased.
|
|
918
|
-
const byoDisclosure = value.storage_profile === "byo" ? ` Storage: byo (${value.byo_destination ?? "(unknown)"}) — ${
|
|
909
|
+
const byoDisclosure = value.storage_profile === "byo" ? ` Storage: byo (${value.byo_destination ?? "(unknown)"}) — ${VAULT_BYO_NO_PAYLOAD_COPY_STATEMENT}` : "";
|
|
919
910
|
checks.push({
|
|
920
|
-
name: "
|
|
911
|
+
name: "vault",
|
|
921
912
|
status: gaps.length > 0 ? "warning" : "ok",
|
|
922
913
|
value: gaps.length > 0 ? { ...value, gaps } : value,
|
|
923
914
|
hint: (gv.vault === null
|
|
@@ -927,12 +918,12 @@ export async function run(sub, args = []) {
|
|
|
927
918
|
: `Back up ${gv.keystore.root} — whole-machine or whole-keystore loss is terminal for vault history.`) + byoDisclosure,
|
|
928
919
|
});
|
|
929
920
|
} catch (err) {
|
|
930
|
-
// A gateway without
|
|
921
|
+
// A gateway without vault, an unreachable API, or a project this
|
|
931
922
|
// wallet cannot see. None of those is a local health problem.
|
|
932
923
|
checks.push({
|
|
933
|
-
name: "
|
|
924
|
+
name: "vault",
|
|
934
925
|
status: "skipped",
|
|
935
|
-
message: describeCheckFailure("
|
|
926
|
+
message: describeCheckFailure("vault status check", err),
|
|
936
927
|
});
|
|
937
928
|
}
|
|
938
929
|
}
|
|
@@ -944,7 +935,7 @@ export async function run(sub, args = []) {
|
|
|
944
935
|
// `error` block deploy (`run402 deploy` wraps doctor and respects exit
|
|
945
936
|
// code). Skipped via --no-scan when the user wants config-only checks, and
|
|
946
937
|
// by any --only that omits it — on a monorepo this check's findings can
|
|
947
|
-
// otherwise bury the
|
|
938
|
+
// otherwise bury the vault diagnosis under thousands of hits.
|
|
948
939
|
if (!skipScan && wanted("source_scan")) {
|
|
949
940
|
try {
|
|
950
941
|
const scope = await resolveApplicationScope({ dir: flagValue(all, "--dir") ?? undefined, manifest: flagValue(all, "--manifest") ?? undefined });
|
package/lib/init.mjs
CHANGED
|
@@ -51,7 +51,7 @@ Options:
|
|
|
51
51
|
nothing; RUN402_AGENT_NAME=<name> sets or overrides it. Change
|
|
52
52
|
it any time with \`run402 whoami --set-name <name>\`.
|
|
53
53
|
--git-remote Also 'git init' the current directory when it is not a
|
|
54
|
-
repository yet, so the
|
|
54
|
+
repository yet, so the vault remote can be added there.
|
|
55
55
|
Opt-in on purpose: init is often run outside a project
|
|
56
56
|
directory and must never create a repository somewhere you
|
|
57
57
|
did not ask it to. Inside an EXISTING repository the remote
|
|
@@ -62,11 +62,11 @@ Output:
|
|
|
62
62
|
tier, projects_saved, active_project_id, next_step }. Progress lines
|
|
63
63
|
(Config / Wallet / Balance / Tier / Next) go to stderr so a human
|
|
64
64
|
re-running interactively sees what's happening while a script piping stdout
|
|
65
|
-
to jq stays clean. The summary also carries {
|
|
66
|
-
remote), or {
|
|
67
|
-
added, or {
|
|
65
|
+
to jq stays clean. The summary also carries { vault } (the scaffolded
|
|
66
|
+
remote), or { vault: null, vault_skipped } naming why no remote was
|
|
67
|
+
added, or { vault: null, vault_error } when it could not be added.
|
|
68
68
|
\`projects_saved\` counts projects with LOCAL keys; \`active_project_id\` is the
|
|
69
|
-
project the
|
|
69
|
+
project the vault scaffold acted on.
|
|
70
70
|
|
|
71
71
|
init scaffolds the git remote only. It does NOT allocate the vault — that is
|
|
72
72
|
\`run402 repos create --project <project_id>\`, which mints key material and a
|
|
@@ -215,13 +215,13 @@ function errorMessage(err) {
|
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
/**
|
|
218
|
-
* Which project the
|
|
218
|
+
* Which project the vault scaffold acts on — and why it may act on none.
|
|
219
219
|
*
|
|
220
220
|
* The CLI-wide resolution order (`RUN402_PROJECT_ID`, then the active
|
|
221
221
|
* project), not `getActiveProjectId()` alone. Reading only the active project
|
|
222
222
|
* meant an agent that had exported `RUN402_PROJECT_ID` — the normal way to
|
|
223
223
|
* address a project without mutating machine state — got a silent no-op: no
|
|
224
|
-
* remote, no allocation, and no `
|
|
224
|
+
* remote, no allocation, and no `vault` key in the summary at all, with
|
|
225
225
|
* nothing anywhere saying `run402 projects use` was a prerequisite
|
|
226
226
|
* (dogfood #1, finding A). A command that exits 0 having done nothing is worse
|
|
227
227
|
* than an error, so the no-project case names itself.
|
|
@@ -375,7 +375,7 @@ export async function run(args = []) {
|
|
|
375
375
|
...(voucherCode ? { voucher: null } : {}),
|
|
376
376
|
tier: null,
|
|
377
377
|
projects_saved: 0,
|
|
378
|
-
/** The project init acted on — the input to the
|
|
378
|
+
/** The project init acted on — the input to the vault scaffold decision. */
|
|
379
379
|
active_project_id: null,
|
|
380
380
|
next_actions: [],
|
|
381
381
|
next_step: null,
|
|
@@ -637,17 +637,17 @@ export async function run(args = []) {
|
|
|
637
637
|
// local keys, so it is legitimately not counted here; `active_project_id`
|
|
638
638
|
// below is the field that says which project init actually acted on, and
|
|
639
639
|
// reading `projects_saved: 0` as "init did nothing" is what made the
|
|
640
|
-
//
|
|
640
|
+
// vault skip look silent (dogfood #1, finding A).
|
|
641
641
|
summary.projects_saved = Object.keys(store.projects).length;
|
|
642
642
|
line("Projects", `${summary.projects_saved} saved`);
|
|
643
643
|
|
|
644
|
-
// 5b.
|
|
644
|
+
// 5b. vault git remote (vault-client-surface, task 5.7).
|
|
645
645
|
//
|
|
646
646
|
// Purely LOCAL git. No vault is allocated and no key material is written
|
|
647
647
|
// here — the spec is explicit that neither exists until first capture, so the
|
|
648
648
|
// cold-start path gains no prompt and no new failure mode. Allocation happens
|
|
649
|
-
// on the first `git push origin <branch>` or `run402
|
|
650
|
-
// repo-first-onramp) — NOT on deploy: `
|
|
649
|
+
// on the first `git push origin <branch>` or `run402 repos capture` (D2,
|
|
650
|
+
// repo-first-onramp) — NOT on deploy: `applyWithVault` only ever reads an
|
|
651
651
|
// EXISTING vault's policy (D3) and never allocates one that does not exist,
|
|
652
652
|
// so a project with no vault deploys exactly as it always did.
|
|
653
653
|
//
|
|
@@ -664,11 +664,11 @@ export async function run(args = []) {
|
|
|
664
664
|
const { projectId: activeProjectId, skipped: noProjectSkip } = resolveScaffoldProject();
|
|
665
665
|
summary.active_project_id = activeProjectId;
|
|
666
666
|
if (noProjectSkip) {
|
|
667
|
-
summary.
|
|
668
|
-
summary.
|
|
669
|
-
line("
|
|
667
|
+
summary.vault = null;
|
|
668
|
+
summary.vault_skipped = noProjectSkip;
|
|
669
|
+
line("Vault", "skipped — no project selected (run402 projects use <project_id>)");
|
|
670
670
|
} else {
|
|
671
|
-
summary.
|
|
671
|
+
summary.vault = null;
|
|
672
672
|
try {
|
|
673
673
|
// Dynamic import: the scaffold is the only thing here that needs the
|
|
674
674
|
// Node SDK's hardened git runner, and a top-level import would drag it
|
|
@@ -681,43 +681,43 @@ export async function run(args = []) {
|
|
|
681
681
|
insideRepo = false;
|
|
682
682
|
}
|
|
683
683
|
if (!insideRepo && !scaffoldGitRemote) {
|
|
684
|
-
summary.
|
|
685
|
-
line("
|
|
684
|
+
summary.vault_skipped = "not a git repository — re-run with --git-remote to create one and add the remote";
|
|
685
|
+
line("Vault", "skipped — not a git repository (--git-remote creates one)");
|
|
686
686
|
} else {
|
|
687
687
|
const orgId = await resolveOwningOrgId(activeProjectId);
|
|
688
688
|
if (!orgId) {
|
|
689
|
-
summary.
|
|
690
|
-
line("
|
|
689
|
+
summary.vault_skipped = `could not resolve the owning org for ${activeProjectId} — the run402 remote was not added`;
|
|
690
|
+
line("Vault", "skipped — owning org unresolved");
|
|
691
691
|
} else {
|
|
692
|
-
const remote = await getSdk().
|
|
692
|
+
const remote = await getSdk().repos.scaffoldRemote({
|
|
693
693
|
repo_dir: process.cwd(),
|
|
694
694
|
org_id: orgId,
|
|
695
695
|
project_id: activeProjectId,
|
|
696
696
|
});
|
|
697
697
|
// `allocated: false` is stated, not left to be inferred: this was
|
|
698
698
|
// local git only, and no vault exists for the project yet.
|
|
699
|
-
summary.
|
|
699
|
+
summary.vault = { ...remote, allocated: false };
|
|
700
700
|
if (remote.already_present && remote.existing_url !== remote.url) {
|
|
701
701
|
// Left exactly as it was. Name the URL that is actually in place
|
|
702
702
|
// rather than implying the remote now points at this project.
|
|
703
|
-
line("
|
|
703
|
+
line("Vault", `remote '${remote.name}' already points at ${remote.existing_url} — left unchanged (${remote.reason})`);
|
|
704
704
|
} else if (remote.already_present) {
|
|
705
|
-
line("
|
|
705
|
+
line("Vault", `remote '${remote.name}' already set (${remote.url})`);
|
|
706
706
|
} else {
|
|
707
707
|
// D1: `origin` when it was free, `run402` when it was already
|
|
708
708
|
// taken by something else — `remote.reason` says which happened.
|
|
709
|
-
line("
|
|
709
|
+
line("Vault", `${remote.created_repository ? "initialized a repository and added" : "added"} remote '${remote.name}' -> ${remote.url} (${remote.reason})`);
|
|
710
710
|
}
|
|
711
711
|
}
|
|
712
712
|
}
|
|
713
713
|
} catch (err) {
|
|
714
714
|
const reason = errorMessage(err);
|
|
715
|
-
summary.
|
|
716
|
-
summary.
|
|
717
|
-
code: err?.body?.code ?? err?.code ?? "
|
|
715
|
+
summary.vault = null;
|
|
716
|
+
summary.vault_error = {
|
|
717
|
+
code: err?.body?.code ?? err?.code ?? "VAULT_SCAFFOLD_FAILED",
|
|
718
718
|
message: reason,
|
|
719
719
|
};
|
|
720
|
-
line("
|
|
720
|
+
line("Vault", `remote not added: ${reason}`);
|
|
721
721
|
}
|
|
722
722
|
}
|
|
723
723
|
|
package/lib/next-actions.mjs
CHANGED
|
@@ -81,7 +81,7 @@ export function upDeployAction() {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* `repos create` (and `
|
|
84
|
+
* `repos create` (and `vault init`) on an org with no slug set: the
|
|
85
85
|
* response's `address: null` had no pointer to WHY, or to the named-addressing
|
|
86
86
|
* feature at all. Owner-only. Wording deliberately
|
|
87
87
|
* omits a price: the first slug per org is free, and renames/re-claims cost
|
package/lib/org-context.mjs
CHANGED
|
@@ -97,15 +97,15 @@ function orgFromRoomEnv(env) {
|
|
|
97
97
|
* `r402.orgId` from `cwd`'s LOCAL git config (kygit-handoff design D10) —
|
|
98
98
|
* best-effort, gracefully degrading like `findBindingKey`: no repository,
|
|
99
99
|
* no pin, or a shape-invalid value all answer `null` rather than throwing,
|
|
100
|
-
* so a bare directory or a checkout with no
|
|
100
|
+
* so a bare directory or a checkout with no vault remote costs nothing.
|
|
101
101
|
* Checks a real vault checkout's pin first (gated on `r402.repoId`), then
|
|
102
102
|
* falls back to the bare org/room pin a room-only `rooms join <key>` writes
|
|
103
103
|
* in a directory with no vault at all (add-room-invite design D10).
|
|
104
104
|
*/
|
|
105
|
-
async function
|
|
105
|
+
async function readVaultPinnedOrgId(cwd) {
|
|
106
106
|
try {
|
|
107
|
-
const {
|
|
108
|
-
const pinned = await
|
|
107
|
+
const { readPinnedVaultRepo, readPinnedRoomBinding } = await import("#sdk/node");
|
|
108
|
+
const pinned = await readPinnedVaultRepo(cwd);
|
|
109
109
|
const orgId = trimmed(pinned?.org_id);
|
|
110
110
|
if (orgId && ORG_ID_RE.test(orgId)) return orgId;
|
|
111
111
|
const bare = await readPinnedRoomBinding(cwd);
|
|
@@ -254,14 +254,14 @@ export async function resolveOrg(input = {}, opts = {}) {
|
|
|
254
254
|
}
|
|
255
255
|
if (bindingOrg) return { orgId: bindingOrg, source: "binding", sourceDetail: bindingHit.file };
|
|
256
256
|
|
|
257
|
-
// --- Class 3.5:
|
|
257
|
+
// --- Class 3.5: vault local pin (kygit-handoff design D10) ------------
|
|
258
258
|
// `r402.orgId` in this checkout's LOCAL git config — written by every
|
|
259
|
-
//
|
|
259
|
+
// vault pin site (`repos create`, `resume`, address resolution), a
|
|
260
260
|
// rung below env/binding and above profile state: a checkout that IS a
|
|
261
261
|
// resumed/pinned vault should resolve its own org with zero configuration,
|
|
262
262
|
// but an explicit env var or a committed `.run402.json` binding still wins.
|
|
263
|
-
const pinnedOrg = await
|
|
264
|
-
if (pinnedOrg) return { orgId: pinnedOrg, source: "
|
|
263
|
+
const pinnedOrg = await readVaultPinnedOrgId(cwd);
|
|
264
|
+
if (pinnedOrg) return { orgId: pinnedOrg, source: "vault_pin", sourceDetail: "r402.orgId (local git config)" };
|
|
265
265
|
|
|
266
266
|
// --- Class 4: profile state ----------------------------------------------
|
|
267
267
|
const selected = trimmed(coreGetActiveOrgId());
|
|
@@ -434,7 +434,7 @@ export function orgProvenance(resolved) {
|
|
|
434
434
|
* owns THIS project id", which is what a project-scoped scaffold needs and
|
|
435
435
|
* where an `--org` override would be a mis-binding, not a convenience.
|
|
436
436
|
*
|
|
437
|
-
* WHY IT CACHES (task 5.12c): the
|
|
437
|
+
* WHY IT CACHES (task 5.12c): the vault scaffold is the one part of
|
|
438
438
|
* `run402 init` the client-surface spec says adds no network dependency to the
|
|
439
439
|
* cold-start path, and resolving the org through `projects.list()` quietly made
|
|
440
440
|
* that untrue. `org_id` is a non-secret routing identifier the control plane
|
package/lib/orgs.mjs
CHANGED
|
@@ -44,7 +44,7 @@ Usage:
|
|
|
44
44
|
run402 orgs members add [<org_id>] <wallet_address> [--role <role>]
|
|
45
45
|
run402 orgs members role [<org_id>] --principal <principal_id> --role <role>
|
|
46
46
|
run402 orgs members rm [<org_id>] --principal <principal_id>
|
|
47
|
-
run402 orgs members revoke-key [<org_id>] --principal <principal_id> [--reason <why>] (owner + step-up; revokes the member's
|
|
47
|
+
run402 orgs members revoke-key [<org_id>] --principal <principal_id> [--reason <why>] (owner + step-up; revokes the member's vault encryption key — its next vault operation enrolls afresh)
|
|
48
48
|
run402 orgs invite list [<org_id>]
|
|
49
49
|
run402 orgs invite create [<org_id>] --email <email> [--role <role>] [--ttl-hours N]
|
|
50
50
|
run402 orgs invite rm [<org_id>] --principal <principal_id>
|
|
@@ -53,7 +53,7 @@ Usage:
|
|
|
53
53
|
omit it and the org comes from --org, then RUN402_ORG, then the .run402.json
|
|
54
54
|
binding, then 'run402 orgs use'. Inside a bound checkout two agents add each
|
|
55
55
|
other with nothing to look up: run402 orgs members add <wallet_address> --role developer.
|
|
56
|
-
A developer-or-above add REFUSES (
|
|
56
|
+
A developer-or-above add REFUSES (VAULT_WRITER_NOT_ADMITTED) unless this session's key is an admitted writer on every vault of the org, so the new member can push at once; a current writer admits your key with run402 repos access sync.
|
|
57
57
|
The second attribute may also be passed positionally (run402 orgs members add <wallet_address>).
|
|
58
58
|
|
|
59
59
|
Subcommands:
|
|
@@ -186,7 +186,7 @@ Usage:
|
|
|
186
186
|
run402 orgs members add [<org_id>] <wallet_address> [--role <role>]
|
|
187
187
|
run402 orgs members role [<org_id>] --principal <principal_id> --role <role>
|
|
188
188
|
run402 orgs members rm [<org_id>] --principal <principal_id>
|
|
189
|
-
run402 orgs members revoke-key [<org_id>] --principal <principal_id> [--reason <why>] (owner + step-up; revokes the member's
|
|
189
|
+
run402 orgs members revoke-key [<org_id>] --principal <principal_id> [--reason <why>] (owner + step-up; revokes the member's vault encryption key — its next vault operation enrolls afresh)
|
|
190
190
|
|
|
191
191
|
Roles: ${ROLE_LIST} (add defaults to developer). Mutations require an active owner.
|
|
192
192
|
Demoting/removing the org's only active owner fails with 409 LAST_OWNER.
|
|
@@ -202,7 +202,7 @@ Usage:
|
|
|
202
202
|
omit it and the org comes from --org, then RUN402_ORG, then the .run402.json
|
|
203
203
|
binding, then 'run402 orgs use'. Inside a bound checkout two agents add each
|
|
204
204
|
other with nothing to look up: run402 orgs members add <wallet_address> --role developer.
|
|
205
|
-
A developer-or-above add REFUSES (
|
|
205
|
+
A developer-or-above add REFUSES (VAULT_WRITER_NOT_ADMITTED) unless this session's key is an admitted writer on every vault of the org, so the new member can push at once; a current writer admits your key with run402 repos access sync.
|
|
206
206
|
The second attribute may also be passed positionally (run402 orgs members add <wallet_address>).
|
|
207
207
|
|
|
208
208
|
An invite is claimed at the recipient's first login. Mutations require an active owner
|
|
@@ -223,7 +223,7 @@ Requires an admin+ membership on the org. Newest-first. Page forward with --afte
|
|
|
223
223
|
|
|
224
224
|
|
|
225
225
|
/**
|
|
226
|
-
*
|
|
226
|
+
* vault-multi-writer (rev 47) task 6.3 / design D3 — decided 2026-09-03
|
|
227
227
|
* (Tal): `orgs members add` REFUSES a writer-eligible add (developer or
|
|
228
228
|
* above) when this session's own key is not an admitted writer on EVERY
|
|
229
229
|
* vault of the org, because a developer who cannot push is not the member
|
|
@@ -237,11 +237,11 @@ Requires an admin+ membership on the org. Newest-first. Page forward with --afte
|
|
|
237
237
|
* Every read failure REFUSES too (an unverifiable gate is not a passed one).
|
|
238
238
|
*/
|
|
239
239
|
async function assertCallerCanAdmitWritersEverywhere(sdk, orgId, effectiveRole) {
|
|
240
|
-
const listing = await sdk.
|
|
240
|
+
const listing = await sdk.repos.listByOrg(orgId);
|
|
241
241
|
const vaults = listing?.vaults ?? [];
|
|
242
242
|
const blocked = [];
|
|
243
243
|
for (const v of vaults) {
|
|
244
|
-
const st = await sdk.
|
|
244
|
+
const st = await sdk.repos.status({ repo_id: v.repo_id, reconcile: "forbidden" });
|
|
245
245
|
const vault = st?.vault ?? null;
|
|
246
246
|
if (!vault || vault.read_only_terminal) continue;
|
|
247
247
|
const me = st?.keystore?.identity_fingerprint ?? null;
|
|
@@ -250,7 +250,7 @@ async function assertCallerCanAdmitWritersEverywhere(sdk, orgId, effectiveRole)
|
|
|
250
250
|
}
|
|
251
251
|
if (blocked.length > 0) {
|
|
252
252
|
fail({
|
|
253
|
-
code: "
|
|
253
|
+
code: "VAULT_WRITER_NOT_ADMITTED",
|
|
254
254
|
message: `refusing to add a ${effectiveRole}: this session's key is not an admitted writer on ${blocked.length} of this org's ${vaults.length} vault(s), so the new member could not push there`,
|
|
255
255
|
details: { role: effectiveRole, vaults: blocked, checked: vaults.length },
|
|
256
256
|
next_actions: [
|
|
@@ -266,7 +266,7 @@ async function assertCallerCanAdmitWritersEverywhere(sdk, orgId, effectiveRole)
|
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
/**
|
|
269
|
-
* `orgs members rm`'s inline epoch rotation (
|
|
269
|
+
* `orgs members rm`'s inline epoch rotation (vault-multi-writer D6, the
|
|
270
270
|
* kygit-handoff member-removal decision): for every vault of the org where
|
|
271
271
|
* this session's key is an admitted writer, drive
|
|
272
272
|
* `rotateEpochForKeyRevocation(principalId)` — the one self-contained
|
|
@@ -275,7 +275,7 @@ async function assertCallerCanAdmitWritersEverywhere(sdk, orgId, effectiveRole)
|
|
|
275
275
|
* no vault (nothing to rotate, nothing to report).
|
|
276
276
|
*/
|
|
277
277
|
async function rotateOrgVaultsAfterRemoval(sdk, orgId, principalId) {
|
|
278
|
-
const listing = await sdk.
|
|
278
|
+
const listing = await sdk.repos.listByOrg(orgId);
|
|
279
279
|
const vaults = listing?.vaults ?? [];
|
|
280
280
|
if (vaults.length === 0) return null;
|
|
281
281
|
const rotated = [];
|
|
@@ -284,7 +284,7 @@ async function rotateOrgVaultsAfterRemoval(sdk, orgId, principalId) {
|
|
|
284
284
|
for (const v of vaults) {
|
|
285
285
|
let st;
|
|
286
286
|
try {
|
|
287
|
-
st = await sdk.
|
|
287
|
+
st = await sdk.repos.status({ repo_id: v.repo_id, reconcile: "forbidden" });
|
|
288
288
|
} catch (err) {
|
|
289
289
|
errors.push({ repo_id: v.repo_id, code: err?.code ?? null, error: err?.message ?? String(err) });
|
|
290
290
|
continue;
|
|
@@ -300,7 +300,7 @@ async function rotateOrgVaultsAfterRemoval(sdk, orgId, principalId) {
|
|
|
300
300
|
try {
|
|
301
301
|
// reason:"member_removed" — writer-capable (no owner step-up); the
|
|
302
302
|
// removal itself advanced the counters this rotation is fenced on.
|
|
303
|
-
const r = await sdk.
|
|
303
|
+
const r = await sdk.repos.rotateEpochForMemberRemoval({ repo_id: v.repo_id });
|
|
304
304
|
rotated.push({ repo_id: v.repo_id, new_epoch: r.new_epoch, generation: r.generation, included: r.included.length, writers_removed: r.writers_removed?.length ?? 0, self_check: r.self_check });
|
|
305
305
|
} catch (err) {
|
|
306
306
|
errors.push({ repo_id: v.repo_id, code: err?.code ?? null, error: err?.message ?? String(err) });
|
|
@@ -717,7 +717,7 @@ async function runMember(args) {
|
|
|
717
717
|
await assertCallerCanAdmitWritersEverywhere(sdk, org, effectiveRole);
|
|
718
718
|
}
|
|
719
719
|
const res = await sdk.org(org).members.add({ wallet, role: role || undefined });
|
|
720
|
-
//
|
|
720
|
+
// vault-multi-writer (rev 47) task 6.3 — the gateway names which of
|
|
721
721
|
// this org's vaults now have a pending writer candidate (D3: there is
|
|
722
722
|
// no server-side writer admission — the client holds the keys) via a
|
|
723
723
|
// `sync_writers` next_action carrying `vault_ids[]`. Run the ACTUAL
|
|
@@ -737,7 +737,7 @@ async function runMember(args) {
|
|
|
737
737
|
const errors = [];
|
|
738
738
|
for (const vaultId of syncTarget.vault_ids) {
|
|
739
739
|
try {
|
|
740
|
-
const r = await sdk.
|
|
740
|
+
const r = await sdk.repos.reconcile({ repo_id: vaultId });
|
|
741
741
|
if (!r.eligible) notEligible.push(vaultId);
|
|
742
742
|
else if (r.admitted.length > 0) admitted.push({ repo_id: vaultId, admitted: r.admitted });
|
|
743
743
|
} catch (err) {
|
|
@@ -748,7 +748,7 @@ async function runMember(args) {
|
|
|
748
748
|
}
|
|
749
749
|
console.log(JSON.stringify(writerSync ? { ...res, writer_sync: writerSync } : res, null, 2));
|
|
750
750
|
if (writerSync?.not_eligible.length > 0) {
|
|
751
|
-
console.error(`writer sync: this session is not (yet) a writer on ${writerSync.not_eligible.length} vault(s) — the new member is a pending writer candidate there until a CURRENT writer's next
|
|
751
|
+
console.error(`writer sync: this session is not (yet) a writer on ${writerSync.not_eligible.length} vault(s) — the new member is a pending writer candidate there until a CURRENT writer's next vault operation admits them.`);
|
|
752
752
|
}
|
|
753
753
|
if (writerSync?.errors.length > 0) {
|
|
754
754
|
for (const e of writerSync.errors) console.error(`writer sync: ${e.repo_id} — ${e.error}`);
|
|
@@ -760,10 +760,10 @@ async function runMember(args) {
|
|
|
760
760
|
}
|
|
761
761
|
|
|
762
762
|
if (memberAction === "revoke-key") {
|
|
763
|
-
//
|
|
764
|
-
//
|
|
763
|
+
// vault-agent-envelopes D3: owner + step-up revokes a member's current
|
|
764
|
+
// vault encryption key — the ONLY rotation path for a member that shares
|
|
765
765
|
// an org with another custodian (a lost/rebuilt keystore fails
|
|
766
|
-
//
|
|
766
|
+
// VAULT_KEY_ROTATION_REQUIRED and points here). Adapter only.
|
|
767
767
|
const a = normalizeArgv(rest);
|
|
768
768
|
assertKnownFlags(a, ["--org", "--principal", "--reason", "--help", "-h"], ["--org", "--principal", "--reason"]);
|
|
769
769
|
const principalFlag = flagValue(a, "--principal");
|
|
@@ -818,7 +818,7 @@ async function runMember(args) {
|
|
|
818
818
|
try {
|
|
819
819
|
const sdk = getSdk();
|
|
820
820
|
const res = await sdk.org(org).members.revoke(principalId);
|
|
821
|
-
//
|
|
821
|
+
// vault-multi-writer D6 — a removal rides `rotate_epoch`: the gateway
|
|
822
822
|
// has just blocked the principal's writer keys and flipped its desired
|
|
823
823
|
// row to pending_removal, so every ordinary push on every vault of this
|
|
824
824
|
// org now refuses EPOCH_ROTATION_REQUIRED until a surviving writer
|