run402 4.95.0 → 4.97.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 +5 -5
- package/cli.mjs +2 -28
- package/core-dist/keystore.js +1 -1
- package/git-remote-run402.mjs +6 -6
- package/lib/buzz.mjs +1 -1
- package/lib/cold-start.mjs +2 -2
- package/lib/command-manifest.mjs +6 -47
- package/lib/credentials.mjs +5 -5
- package/lib/daemon-path.mjs +3 -3
- package/lib/deploy-v2.mjs +44 -44
- package/lib/doctor.mjs +45 -54
- package/lib/errors.mjs +1 -1
- package/lib/events.mjs +1 -1
- package/lib/grants.mjs +148 -46
- package/lib/init.mjs +29 -29
- package/lib/logs.mjs +1 -1
- 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/projects.mjs +1 -1
- package/lib/remote-helper-session.mjs +93 -93
- package/lib/repos.mjs +174 -175
- package/lib/rooms-context.mjs +7 -7
- package/lib/sites.mjs +5 -5
- 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 +5 -5
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js +2 -2
- package/sdk/dist/errors.js.map +1 -1
- package/sdk/dist/grant-key-credentials.d.ts +38 -0
- package/sdk/dist/grant-key-credentials.d.ts.map +1 -0
- package/sdk/dist/grant-key-credentials.js +42 -0
- package/sdk/dist/grant-key-credentials.js.map +1 -0
- package/sdk/dist/index.d.ts +16 -23
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +14 -21
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/namespaces/billing.d.ts +1 -1
- package/sdk/dist/namespaces/billing.js +1 -1
- package/sdk/dist/namespaces/buzz.js +1 -1
- package/sdk/dist/namespaces/buzz.js.map +1 -1
- package/sdk/dist/namespaces/credentials.d.ts +4 -4
- package/sdk/dist/namespaces/credentials.js +4 -4
- 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 +25 -25
- 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/domains.d.ts +1 -1
- package/sdk/dist/namespaces/domains.js +1 -1
- package/sdk/dist/namespaces/errors.d.ts +1 -1
- package/sdk/dist/namespaces/errors.js +2 -2
- package/sdk/dist/namespaces/escalations.d.ts +2 -2
- package/sdk/dist/namespaces/escalations.js +2 -2
- package/sdk/dist/namespaces/escalations.types.d.ts +3 -3
- package/sdk/dist/namespaces/escalations.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/events.d.ts +1 -1
- package/sdk/dist/namespaces/events.js +1 -1
- package/sdk/dist/namespaces/functions.js +1 -1
- package/sdk/dist/namespaces/functions.js.map +1 -1
- package/sdk/dist/namespaces/grants.d.ts +43 -9
- package/sdk/dist/namespaces/grants.d.ts.map +1 -1
- package/sdk/dist/namespaces/grants.js +99 -10
- package/sdk/dist/namespaces/grants.js.map +1 -1
- package/sdk/dist/namespaces/grants.types.d.ts +120 -15
- package/sdk/dist/namespaces/grants.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/grants.types.js +12 -3
- package/sdk/dist/namespaces/grants.types.js.map +1 -1
- package/sdk/dist/namespaces/identity-links.types.d.ts +2 -2
- package/sdk/dist/namespaces/identity-links.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/org.d.ts +3 -3
- package/sdk/dist/namespaces/org.js +3 -3
- package/sdk/dist/namespaces/org.types.d.ts +3 -3
- package/sdk/dist/namespaces/pay.js +1 -1
- package/sdk/dist/namespaces/projects.d.ts +1 -1
- package/sdk/dist/namespaces/projects.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} +452 -460
- package/sdk/dist/namespaces/repos.js.map +1 -0
- package/sdk/dist/namespaces/rooms.d.ts +3 -3
- package/sdk/dist/namespaces/rooms.js +5 -5
- 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/credentials.d.ts +9 -9
- package/sdk/dist/node/credentials.d.ts.map +1 -1
- package/sdk/dist/node/credentials.js +12 -12
- package/sdk/dist/node/credentials.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 +34 -34
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +41 -41
- 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/sdk/dist/project-auth-classification.d.ts +8 -8
- package/sdk/dist/project-auth-classification.d.ts.map +1 -1
- package/sdk/dist/project-auth-classification.js +7 -7
- package/sdk/dist/project-auth-classification.js.map +1 -1
- package/sdk/dist/scoped.d.ts +6 -14
- package/sdk/dist/scoped.d.ts.map +1 -1
- package/sdk/dist/scoped.js +10 -21
- package/sdk/dist/scoped.js.map +1 -1
- package/vault-surface.json +40 -0
- package/gitvault-surface.json +0 -89
- package/lib/delegates.mjs +0 -189
- package/lib/gitvault.mjs +0 -163
- package/lib/source-access.mjs +0 -70
- package/sdk/dist/delegate-credentials.d.ts +0 -37
- package/sdk/dist/delegate-credentials.d.ts.map +0 -1
- package/sdk/dist/delegate-credentials.js +0 -41
- package/sdk/dist/delegate-credentials.js.map +0 -1
- package/sdk/dist/namespaces/delegates.d.ts +0 -50
- package/sdk/dist/namespaces/delegates.d.ts.map +0 -1
- package/sdk/dist/namespaces/delegates.js +0 -99
- package/sdk/dist/namespaces/delegates.js.map +0 -1
- package/sdk/dist/namespaces/delegates.types.d.ts +0 -88
- package/sdk/dist/namespaces/delegates.types.d.ts.map +0 -1
- package/sdk/dist/namespaces/delegates.types.js +0 -10
- package/sdk/dist/namespaces/delegates.types.js.map +0 -1
- 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/repos.mjs
CHANGED
|
@@ -2,24 +2,17 @@
|
|
|
2
2
|
* `run402 repos` — the consolidated encrypted-repository family. One noun,
|
|
3
3
|
* thirteen verbs, each one either a `gh repo` verb, a `git` verb meaning what
|
|
4
4
|
* it means in git, or a plain-English verb for an operation with no analog.
|
|
5
|
-
* `repo` singular resolves identically (`cli.mjs` dispatches both spellings
|
|
6
|
-
* here).
|
|
7
5
|
*
|
|
8
6
|
* ARCHITECTURAL LAW: every piece of protocol behavior — crypto core,
|
|
9
7
|
* keystore, creation journal, snapshot + capture, publication state
|
|
10
8
|
* machines, ref transactions, verification budget, repair — lives ONCE in
|
|
11
|
-
* `@run402/sdk` under `r.
|
|
12
|
-
* infrastructure language). This module is a THIN ADAPTER: argument
|
|
9
|
+
* `@run402/sdk` under `r.repos`. This module is a THIN ADAPTER: argument
|
|
13
10
|
* parsing, TTY output, exit codes, local file I/O. It adds zero protocol
|
|
14
11
|
* behavior of its own.
|
|
15
12
|
*
|
|
16
13
|
* Pipe contract (docs/style.md): the payload is JSON on stdout; every human
|
|
17
14
|
* line (progress, the terminal-loss statement, advisories) goes to stderr,
|
|
18
15
|
* so `run402 repos view | jq` stays clean.
|
|
19
|
-
*
|
|
20
|
-
* `cli/lib/gitvault.mjs` is a tombstone that answers every `gitvault <verb>`
|
|
21
|
-
* spelling with a typed `COMMAND_MOVED` (naming its `repos` successor) or
|
|
22
|
-
* `COMMAND_REMOVED` (for `reconcile`, which has none) error.
|
|
23
16
|
*/
|
|
24
17
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
25
18
|
import { basename, join } from "node:path";
|
|
@@ -29,17 +22,16 @@ import { withAutoApprove } from "./sign-in.mjs";
|
|
|
29
22
|
import { walletAuthHeaders, isCoreApiTarget, readWallet, resolveProjectId } from "./config.mjs";
|
|
30
23
|
import { loadLiveControlPlaneSession } from "../core-dist/control-plane-session.js";
|
|
31
24
|
import { resolveOrgId, resolveOwningOrgId } from "./org-context.mjs";
|
|
32
|
-
import {
|
|
25
|
+
import { resolveVaultTarget } from "./vault-target.mjs";
|
|
33
26
|
import { nextAction, setOrgSlugAction, setRepoNameAction } from "./next-actions.mjs";
|
|
34
27
|
import { resolveHarnessLabels, resolveSessionKey, resolveTaskLabel, persistSessionKey } from "./harness-context.mjs";
|
|
35
28
|
import { updateRoomState } from "./rooms-context.mjs";
|
|
36
|
-
import { printKeystoreLocation } from "./gitvault.mjs";
|
|
37
29
|
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
VAULT_BYO_HEADLINE_STATEMENT,
|
|
31
|
+
VAULT_BYO_NO_PAYLOAD_COPY_STATEMENT,
|
|
32
|
+
VAULT_BYO_UNMIRRORED_REMEDY_STATEMENT,
|
|
33
|
+
VAULT_MIRROR_SETUP_HINT,
|
|
34
|
+
vaultRemoteUrlForRepo,
|
|
43
35
|
} from "#sdk";
|
|
44
36
|
import { sdkStats, printVerboseStats, isVerbose } from "./stats.mjs";
|
|
45
37
|
import {
|
|
@@ -54,6 +46,19 @@ import {
|
|
|
54
46
|
validateRegularFile,
|
|
55
47
|
} from "./argparse.mjs";
|
|
56
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Where the keystore lives — printed after `repos create` allocates and
|
|
51
|
+
* after `repos capture` publishes.
|
|
52
|
+
*/
|
|
53
|
+
async function printKeystoreLocation() {
|
|
54
|
+
try {
|
|
55
|
+
const { getVaultKeystoreRoot } = await import("#sdk/node");
|
|
56
|
+
console.error(`keystore: ${getVaultKeystoreRoot()} — back this up; whole-keystore loss is terminal for repo history`);
|
|
57
|
+
} catch {
|
|
58
|
+
// Never let a diagnostic line fail a command that already succeeded.
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
57
62
|
/** Value-taking flags every vault-targeting subcommand accepts. */
|
|
58
63
|
const COMMON_VALUE_FLAGS = ["--project", "--repo"];
|
|
59
64
|
|
|
@@ -85,7 +90,7 @@ Invite (bring a second agent into the SAME work, dirty tree included):
|
|
|
85
90
|
run402 repos join <kgi1_…|--key-stdin> [--to <dir>] [--no-init] [--json]
|
|
86
91
|
|
|
87
92
|
Occasional:
|
|
88
|
-
run402 repos
|
|
93
|
+
run402 repos capture [--project <project_id>] [--repo <repo_id>] [--message <text>] [--checkpoint] [--dry-run] [--allow-dirty] [--manifest-out <path>]
|
|
89
94
|
run402 repos mirror [<destination>] [--off] [--backfill] [--profile <name> | --ambient] [--region <r>] [--endpoint <url>] [--project <project_id>] [--repo <repo_id>]
|
|
90
95
|
run402 repos recover <source> --out <dir> [--repo <repo_id>] [--profile <name> | --ambient] [--region <r>] [--endpoint <url>]
|
|
91
96
|
[--bundle <file>] [--code <SRC1-…>] [--receipt <file>] [--rp-id <host>] [--human]
|
|
@@ -98,7 +103,7 @@ Lifecycle:
|
|
|
98
103
|
Maintenance:
|
|
99
104
|
run402 repos fsck [--project <project_id>] [--repo <repo_id>] [--mirror] [--budget <n>] [--no-write] [--human]
|
|
100
105
|
run402 repos gc [--project <project_id>] [--repo <repo_id>] [--force-headroom] [--submit --intent-core <path> --verifier-receipt <path> [--wait]]
|
|
101
|
-
run402 repos daemon <status|stop> The resident helper engine (
|
|
106
|
+
run402 repos daemon <status|stop> The resident helper engine (vault-persistent-helper) — inspect or retire it; nothing requires either
|
|
102
107
|
run402 repos access [--project <project_id>] [--repo <repo_id>] [--human]
|
|
103
108
|
run402 repos access repair [--project <project_id>] [--repo <repo_id>] --recipient-state-version <n> --recipient-revocation-version <n>
|
|
104
109
|
run402 repos access revoke-key <principal_id> [--project <project_id>] [--repo <repo_id>]
|
|
@@ -149,7 +154,7 @@ Subcommands:
|
|
|
149
154
|
omitted. \`--human\` renders a compact roster (address,
|
|
150
155
|
generation, bytes, policy) instead of JSON.
|
|
151
156
|
handoff Capture a stash-shaped checkpoint (dirty work included, by
|
|
152
|
-
default — unlike \`
|
|
157
|
+
default — unlike \`capture\`) and mint a single-use Handoff Key
|
|
153
158
|
(\`kgh1_…\`), printed ONCE to stdout; the blast-radius warning
|
|
154
159
|
("anyone holding this key becomes a <role> of this org until
|
|
155
160
|
first use or <expires_at>") and every other line go to stderr.
|
|
@@ -214,8 +219,8 @@ Subcommands:
|
|
|
214
219
|
confirmation below it (the repo holds admitted generations); it
|
|
215
220
|
NEVER overrides the non-repo-infra refusal. Success enumerates
|
|
216
221
|
deleted_resources.
|
|
217
|
-
|
|
218
|
-
a vault-only repo
|
|
222
|
+
capture Capture the working tree and publish it. Not gated on a deploy —
|
|
223
|
+
a vault-only repo captures for months without one. Against a
|
|
219
224
|
project with no vault yet, this ALLOCATES one inline before
|
|
220
225
|
publishing. Push-to-creates through a slug-form remote
|
|
221
226
|
(run402::<org-slug>/<name>) the same way \`git push\` does.
|
|
@@ -226,7 +231,7 @@ Subcommands:
|
|
|
226
231
|
capture it as-is; the result then discloses exactly what was
|
|
227
232
|
swept in (modified_captured / untracked_captured), printed to
|
|
228
233
|
stderr too. \`--dry-run\` surfaces the same refusal.
|
|
229
|
-
Both \`--dry-run\` and a real
|
|
234
|
+
Both \`--dry-run\` and a real capture print a SUMMARY by default —
|
|
230
235
|
file counts (files_total/files_changed/files_new), total/delta
|
|
231
236
|
bytes, and up to 200 changed/new paths (changed_more names any
|
|
232
237
|
overflow) — never the full captured-file inventory, which can run
|
|
@@ -241,7 +246,7 @@ Subcommands:
|
|
|
241
246
|
freshness check against the live vault. \`<destination>\`:
|
|
242
247
|
configure (idempotent upsert). \`--off\`: remove the config only —
|
|
243
248
|
never touches the mirror's own bytes. \`--backfill\`: copy every
|
|
244
|
-
object the mirror is missing (every
|
|
249
|
+
object the mirror is missing (every capture is already mirrored
|
|
245
250
|
automatically; backfill exists for a pre-existing vault or a
|
|
246
251
|
mirror that fell behind). Exactly one of these per call. Mirror
|
|
247
252
|
state also renders inside \`repos view\`; mirror INTEGRITY inside
|
|
@@ -298,7 +303,7 @@ Subcommands:
|
|
|
298
303
|
the customer's own bucket against run402's signed chain —
|
|
299
304
|
automatic, no flag needed. No local BYO credentials on this
|
|
300
305
|
machine reports an explicit NOT CHECKED line, never a failure;
|
|
301
|
-
a confirmed absence FAILS fsck with
|
|
306
|
+
a confirmed absence FAILS fsck with VAULT_BYO_OBJECT_MISSING
|
|
302
307
|
naming exactly what's missing. Runs under \`--no-write\` too (a
|
|
303
308
|
pure HEAD-check read). See the result's \`byo_presence\` block
|
|
304
309
|
(also on \`--human\`); absent entirely for a managed vault.
|
|
@@ -330,9 +335,9 @@ Subcommands:
|
|
|
330
335
|
actually rotates. history_scope (which epochs each recipient can
|
|
331
336
|
read) is not reported by this read — see the \`gap\` field. An
|
|
332
337
|
enrolled teammate's key envelope is wrapped AUTOMATICALLY — no
|
|
333
|
-
manual step — by the next \`git push\` or \`repos
|
|
338
|
+
manual step — by the next \`git push\` or \`repos capture\` any
|
|
334
339
|
key-holding client runs (best-effort, non-blocking; the retired
|
|
335
|
-
\`
|
|
340
|
+
\`vault reconcile\` verb did this by hand and is REMOVED).
|
|
336
341
|
\`--human\` renders a compact roster instead of JSON (the read
|
|
337
342
|
form only — repair/revoke-key/declare-exposure stay JSON-only).
|
|
338
343
|
access repair
|
|
@@ -368,7 +373,7 @@ Subcommands:
|
|
|
368
373
|
policy auto-gc [<generations>|off]
|
|
369
374
|
A LOCAL, per-checkout setting (git config, like git's own
|
|
370
375
|
\`gc.auto\` — no network call, no --project/--repo/--reason): the
|
|
371
|
-
post-push compaction cadence (
|
|
376
|
+
post-push compaction cadence (vault-checkpoint-cadence).
|
|
372
377
|
Default 32 — after a push, once this many generations have
|
|
373
378
|
accumulated since the vault's last checkpoint, \`gc\`'s
|
|
374
379
|
compact+prune-plan cycle runs automatically (one stderr advisory
|
|
@@ -414,19 +419,19 @@ Options:
|
|
|
414
419
|
--force delete: proceed even though the repo holds generations
|
|
415
420
|
that would be permanently and irrecoverably lost. Never
|
|
416
421
|
overrides the non-repo-infrastructure refusal.
|
|
417
|
-
--message <text>
|
|
422
|
+
--message <text> capture: commit message for the synthetic commit a dirty
|
|
418
423
|
tree produces (a clean tree pushes HEAD itself, unused)
|
|
419
|
-
--checkpoint
|
|
420
|
-
--dry-run
|
|
424
|
+
--checkpoint capture: force the checkpoint-bearing form regardless of delta size
|
|
425
|
+
--dry-run capture: a REAL preview — runs the actual local pipeline
|
|
421
426
|
and reports what would publish. Publishes nothing. A
|
|
422
427
|
dirty tree still refuses SNAPSHOT_DIRTY_TREE here (a
|
|
423
428
|
preview that hid the refusal would lie).
|
|
424
|
-
--allow-dirty
|
|
429
|
+
--allow-dirty capture: capture a dirty tree as-is instead of refusing.
|
|
425
430
|
The result discloses exactly what was swept in
|
|
426
431
|
(modified_captured / untracked_captured) — even this
|
|
427
432
|
override never captures silently.
|
|
428
433
|
--manifest-out <path>
|
|
429
|
-
|
|
434
|
+
capture: write the complete captured-file inventory
|
|
430
435
|
(the full JSON the SDK returned, untouched) to a private
|
|
431
436
|
0600 file instead of stdout's default summary. The
|
|
432
437
|
printed result's manifest_path names it. Composes with
|
|
@@ -486,7 +491,7 @@ Options:
|
|
|
486
491
|
-v, --verbose Print one stderr summary line of this call's request
|
|
487
492
|
stats (round trips, wire time, bytes). Coexists with
|
|
488
493
|
--human. The JSON result always carries a \`stats\` block
|
|
489
|
-
regardless of this flag. On \`
|
|
494
|
+
regardless of this flag. On \`capture\`/\`capture
|
|
490
495
|
--dry-run\`, ALSO inlines the full captured-file
|
|
491
496
|
inventory in stdout's JSON (composes with the stats
|
|
492
497
|
line — both happen, not one or the other).
|
|
@@ -505,9 +510,9 @@ Examples:
|
|
|
505
510
|
run402 repos view --human
|
|
506
511
|
run402 repos list --org org_1a2b3c --human
|
|
507
512
|
run402 repos rename my-notes --project prj_1a2b3c
|
|
508
|
-
run402 repos
|
|
509
|
-
run402 repos
|
|
510
|
-
run402 repos
|
|
513
|
+
run402 repos capture --dry-run
|
|
514
|
+
run402 repos capture --dry-run --manifest-out /tmp/capture-plan.json
|
|
515
|
+
run402 repos capture --allow-dirty
|
|
511
516
|
run402 repos mirror s3://acme-vault-mirror --profile acme
|
|
512
517
|
run402 repos mirror --backfill
|
|
513
518
|
run402 repos fsck --mirror --human
|
|
@@ -530,7 +535,7 @@ async function vaultTarget(a) {
|
|
|
530
535
|
const repoId = flagValue(a, "--repo");
|
|
531
536
|
const project = flagValue(a, "--project");
|
|
532
537
|
const repoDir = process.cwd();
|
|
533
|
-
const resolved = await
|
|
538
|
+
const resolved = await resolveVaultTarget({
|
|
534
539
|
repoDir,
|
|
535
540
|
explicitProjectId: project ?? undefined,
|
|
536
541
|
explicitRepoId: repoId ?? undefined,
|
|
@@ -592,8 +597,8 @@ async function spillIfLarge(repoId, verb, payload) {
|
|
|
592
597
|
const json = JSON.stringify(payload, null, 2);
|
|
593
598
|
if (Buffer.byteLength(json, "utf8") <= LARGE_OUTPUT_THRESHOLD_BYTES) return;
|
|
594
599
|
try {
|
|
595
|
-
const {
|
|
596
|
-
const dir = join(
|
|
600
|
+
const { getVaultKeystoreRoot } = await import("#sdk/node");
|
|
601
|
+
const dir = join(getVaultKeystoreRoot(), "reports");
|
|
597
602
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
598
603
|
const path = join(dir, `${verb}-${repoId ?? "unknown"}-${Date.now()}.json`);
|
|
599
604
|
writeFileSync(path, json, { mode: 0o600 });
|
|
@@ -670,11 +675,11 @@ async function formatRepoHuman(s, mirror) {
|
|
|
670
675
|
const objectCount = storage?.objects ? Object.values(storage.objects).reduce((sum, n) => sum + Number(n), 0) : null;
|
|
671
676
|
lines.push(storage ? `Storage: ${storage.source_bytes} byte(s)${objectCount != null ? ` across ${objectCount} object(s)` : ""}` : "Storage: unknown");
|
|
672
677
|
|
|
673
|
-
//
|
|
678
|
+
// vault-byo-primary-bucket task 3.5 — unconditional, independent of
|
|
674
679
|
// mirror status (D7).
|
|
675
680
|
if (s.vault.storage_profile === "byo") {
|
|
676
|
-
lines.push(`Storage profile: byo (${s.vault.byo_destination ?? "(unknown)"}) — ${
|
|
677
|
-
lines.push(
|
|
681
|
+
lines.push(`Storage profile: byo (${s.vault.byo_destination ?? "(unknown)"}) — ${VAULT_BYO_HEADLINE_STATEMENT}`);
|
|
682
|
+
lines.push(VAULT_BYO_NO_PAYLOAD_COPY_STATEMENT);
|
|
678
683
|
}
|
|
679
684
|
|
|
680
685
|
const decryptPart = !s.keystore.holds_repo_key
|
|
@@ -682,9 +687,9 @@ async function formatRepoHuman(s, mirror) {
|
|
|
682
687
|
: s.keystore.can_sign
|
|
683
688
|
? "can decrypt and publish"
|
|
684
689
|
: "can decrypt (read-only — no signing key)";
|
|
685
|
-
lines.push(`This machine: ${decryptPart}. Policy: ${s.
|
|
690
|
+
lines.push(`This machine: ${decryptPart}. Policy: ${s.vault_policy ?? "(none)"}`);
|
|
686
691
|
|
|
687
|
-
//
|
|
692
|
+
// vault-multi-writer (rev 47) task 6.1 — the writer roster, one line
|
|
688
693
|
// per writer: `writer_set` is the chain-verified set exactly as `verify`/
|
|
689
694
|
// `fsck` would derive it (never re-verified here — this is `view`'s own
|
|
690
695
|
// side-effect-free read of the vault RECORD's already-verified pointer).
|
|
@@ -707,7 +712,7 @@ async function formatRepoHuman(s, mirror) {
|
|
|
707
712
|
}
|
|
708
713
|
}
|
|
709
714
|
|
|
710
|
-
//
|
|
715
|
+
// vault-mirror-default: the SDK-computed vault_unmirrored finding is
|
|
711
716
|
// echoed verbatim (never rephrased here) — informational, never blocking.
|
|
712
717
|
if (mirror?.finding) {
|
|
713
718
|
lines.push(`Mirror (${mirror.finding.kind}): ${mirror.finding.message} — ${mirror.finding.setup_command}`);
|
|
@@ -749,7 +754,7 @@ function slugifyRepoName(name) {
|
|
|
749
754
|
.replace(/-+$/g, "");
|
|
750
755
|
}
|
|
751
756
|
|
|
752
|
-
/** The basename of an existing `run402`/`origin` remote's URL, or `null` when there is no repository or no such remote. Any remote — a GitHub URL parses fine too, not only a
|
|
757
|
+
/** The basename of an existing `run402`/`origin` remote's URL, or `null` when there is no repository or no such remote. Any remote — a GitHub URL parses fine too, not only a vault address. */
|
|
753
758
|
async function remoteBasenameCandidate(dir) {
|
|
754
759
|
try {
|
|
755
760
|
const { hardenedGit } = await import("#sdk/node");
|
|
@@ -821,7 +826,7 @@ async function inferRepoName(dir) {
|
|
|
821
826
|
|
|
822
827
|
const CREATE_VALUE_FLAGS = ["--org", "--dir", "--tier", "--idempotency-key", "--project", "--byo", "--profile", "--region", "--endpoint"];
|
|
823
828
|
|
|
824
|
-
/**
|
|
829
|
+
/** vault-byo-primary-bucket task 3.5 — `--byo <destination>` + the SAME credential/region/endpoint flags `repos mirror` already uses. `undefined` when `--byo` was not passed (byte-identical to today). */
|
|
825
830
|
function resolveByoOption(a) {
|
|
826
831
|
const destinationUrl = flagValue(a, "--byo");
|
|
827
832
|
if (destinationUrl == null) return undefined;
|
|
@@ -847,7 +852,7 @@ async function printCreateResult({ sdk, projectId, vault, adopted, name, verbose
|
|
|
847
852
|
const candidate = slugifyRepoName(name);
|
|
848
853
|
if (candidate) {
|
|
849
854
|
const named = await sdk.projects.setRepoName(projectId, candidate);
|
|
850
|
-
address =
|
|
855
|
+
address = vaultRemoteUrlForRepo(orgSlug, named.repo_name);
|
|
851
856
|
}
|
|
852
857
|
}
|
|
853
858
|
} catch (err) {
|
|
@@ -864,14 +869,14 @@ async function printCreateResult({ sdk, projectId, vault, adopted, name, verbose
|
|
|
864
869
|
: null;
|
|
865
870
|
const remoteSkippedActions = vault.remote?.status === "skipped" ? (vault.remote.next_actions ?? []) : [];
|
|
866
871
|
const nameAction = address ? null : orgSlug ? setRepoNameAction(projectId) : setOrgSlugAction();
|
|
867
|
-
//
|
|
872
|
+
// vault-byo-primary-bucket task 3.5: a BYO vault's "add a copy" remedy
|
|
868
873
|
// names a SECOND customer-held location (D7) — the plain mirror hint
|
|
869
874
|
// frames the mirror as the FIRST custody-held copy, which is false once
|
|
870
875
|
// the vault's own primary bucket already is one.
|
|
871
876
|
const isByo = vault.storage_profile === "byo";
|
|
872
877
|
const mirrorAction = isByo
|
|
873
|
-
? nextAction("configure_mirror", { command: "run402 repos mirror <destination>", why:
|
|
874
|
-
: nextAction("configure_mirror", { command: "run402 repos mirror <destination>", why:
|
|
878
|
+
? nextAction("configure_mirror", { command: "run402 repos mirror <destination>", why: VAULT_BYO_UNMIRRORED_REMEDY_STATEMENT })
|
|
879
|
+
: nextAction("configure_mirror", { command: "run402 repos mirror <destination>", why: VAULT_MIRROR_SETUP_HINT });
|
|
875
880
|
const nextActions = [pushAction, ...remoteSkippedActions, mirrorAction, nameAction].filter(Boolean);
|
|
876
881
|
|
|
877
882
|
// Secret-bearing (recovery_receipt): built fresh every call, printed once,
|
|
@@ -908,11 +913,11 @@ async function printCreateResult({ sdk, projectId, vault, adopted, name, verbose
|
|
|
908
913
|
if (pushAction) console.error(`next: ${pushAction.command}`);
|
|
909
914
|
for (const action of remoteSkippedActions) if (action?.command) console.error(`next: ${action.command}`);
|
|
910
915
|
if (isByo) {
|
|
911
|
-
console.error(`storage: byo (${vault.byo_destination}) — ${
|
|
912
|
-
console.error(
|
|
913
|
-
console.error(
|
|
916
|
+
console.error(`storage: byo (${vault.byo_destination}) — ${VAULT_BYO_HEADLINE_STATEMENT}`);
|
|
917
|
+
console.error(VAULT_BYO_NO_PAYLOAD_COPY_STATEMENT);
|
|
918
|
+
console.error(VAULT_BYO_UNMIRRORED_REMEDY_STATEMENT);
|
|
914
919
|
} else {
|
|
915
|
-
console.error(
|
|
920
|
+
console.error(VAULT_MIRROR_SETUP_HINT);
|
|
916
921
|
}
|
|
917
922
|
console.error("");
|
|
918
923
|
console.error(vault.terminal_loss_statement);
|
|
@@ -927,7 +932,7 @@ async function createAdopt(projectId, dir, a) {
|
|
|
927
932
|
const orgId = flagValue(a, "--org") ?? await resolveOwningOrgId(projectId);
|
|
928
933
|
if (!orgId) {
|
|
929
934
|
fail({
|
|
930
|
-
code: "
|
|
935
|
+
code: "VAULT_ORG_UNRESOLVED",
|
|
931
936
|
message: `Could not resolve the organization that owns ${projectId}.`,
|
|
932
937
|
hint: "Pass --org <org_id>, or check that this wallet can see the project (`run402 projects list`).",
|
|
933
938
|
details: { project_id: projectId },
|
|
@@ -935,7 +940,7 @@ async function createAdopt(projectId, dir, a) {
|
|
|
935
940
|
}
|
|
936
941
|
try {
|
|
937
942
|
const byo = resolveByoOption(a);
|
|
938
|
-
const vault = await sdk.
|
|
943
|
+
const vault = await sdk.repos.init({ org_id: orgId, project_id: projectId, repo_dir: dir, ...(a.includes("--nested") ? { nested: true } : {}), ...(byo ? { byo } : {}) });
|
|
939
944
|
await printCreateResult({ sdk, projectId, vault, adopted: true, name: null, verboseArgv: a });
|
|
940
945
|
} catch (err) {
|
|
941
946
|
reportSdkError(err);
|
|
@@ -1008,7 +1013,7 @@ async function createProvision(name, dir, a) {
|
|
|
1008
1013
|
const effectiveOrgId = orgId ?? (await resolveOwningOrgId(provisioned.project_id));
|
|
1009
1014
|
if (!effectiveOrgId) {
|
|
1010
1015
|
fail({
|
|
1011
|
-
code: "
|
|
1016
|
+
code: "VAULT_ORG_UNRESOLVED",
|
|
1012
1017
|
message: `Provisioned project ${provisioned.project_id}, but could not resolve its owning organization to allocate the repo.`,
|
|
1013
1018
|
hint: `Pass --org <org_id> next time, or finish by hand: run402 repos create --project ${provisioned.project_id} --org <org_id>`,
|
|
1014
1019
|
details: { project_id: provisioned.project_id },
|
|
@@ -1018,7 +1023,7 @@ async function createProvision(name, dir, a) {
|
|
|
1018
1023
|
|
|
1019
1024
|
try {
|
|
1020
1025
|
const byo = resolveByoOption(a);
|
|
1021
|
-
const vault = await sdk.
|
|
1026
|
+
const vault = await sdk.repos.init({ org_id: effectiveOrgId, project_id: provisioned.project_id, repo_dir: dir, ...(a.includes("--nested") ? { nested: true } : {}), ...(byo ? { byo } : {}) });
|
|
1022
1027
|
await printCreateResult({ sdk, projectId: provisioned.project_id, vault, adopted: false, name, verboseArgv: a });
|
|
1023
1028
|
} catch (err) {
|
|
1024
1029
|
reportSdkError(err);
|
|
@@ -1062,14 +1067,14 @@ async function create(args) {
|
|
|
1062
1067
|
|
|
1063
1068
|
/** The FROZEN bulk-read shape (task 2.4) — one round trip. */
|
|
1064
1069
|
async function listViaBulkRead(sdk, orgId) {
|
|
1065
|
-
const result = await sdk.
|
|
1070
|
+
const result = await sdk.repos.listByOrg(orgId);
|
|
1066
1071
|
return Array.isArray(result.vaults) ? result.vaults : [];
|
|
1067
1072
|
}
|
|
1068
1073
|
|
|
1069
1074
|
/**
|
|
1070
1075
|
* DEPRECATED fallback, kept only until every deployed gateway answers
|
|
1071
|
-
* `GET /
|
|
1072
|
-
* org's projects, then read each one's
|
|
1076
|
+
* `GET /vaults/v1?org_id=`: the old client-side N+1 (list the
|
|
1077
|
+
* org's projects, then read each one's vault status). Delete this
|
|
1073
1078
|
* function once the bulk route has shipped long enough that no gateway
|
|
1074
1079
|
* still 404s it.
|
|
1075
1080
|
*/
|
|
@@ -1080,7 +1085,7 @@ async function listViaFallback(sdk, orgId) {
|
|
|
1080
1085
|
for (const p of projects) {
|
|
1081
1086
|
let status;
|
|
1082
1087
|
try {
|
|
1083
|
-
status = await sdk.
|
|
1088
|
+
status = await sdk.repos.status({ project_id: p.id });
|
|
1084
1089
|
} catch {
|
|
1085
1090
|
continue;
|
|
1086
1091
|
}
|
|
@@ -1091,7 +1096,7 @@ async function listViaFallback(sdk, orgId) {
|
|
|
1091
1096
|
project_name: p.name ?? null,
|
|
1092
1097
|
repo_name: null,
|
|
1093
1098
|
org_slug: null,
|
|
1094
|
-
|
|
1099
|
+
vault_policy: status.vault.vault_policy,
|
|
1095
1100
|
newest_generation: status.vault.newest_generation ?? null,
|
|
1096
1101
|
source_bytes: String(status.vault.storage?.source_bytes ?? "0"),
|
|
1097
1102
|
genesis_admitted_at: status.vault.genesis_admitted_at,
|
|
@@ -1107,8 +1112,8 @@ async function formatRepoListHuman(orgSlug, repos) {
|
|
|
1107
1112
|
const { generationToBigInt } = await import("#sdk/node");
|
|
1108
1113
|
const decimal = (g) => (g ? generationToBigInt(g).toString() : "none");
|
|
1109
1114
|
const lines = repos.map((r) => {
|
|
1110
|
-
const address = orgSlug && r.repo_name ?
|
|
1111
|
-
return `${address} gen=${decimal(r.newest_generation)} ${r.source_bytes} byte(s) policy=${r.
|
|
1115
|
+
const address = orgSlug && r.repo_name ? vaultRemoteUrlForRepo(orgSlug, r.repo_name) : (r.repo_name ?? r.project_id);
|
|
1116
|
+
return `${address} gen=${decimal(r.newest_generation)} ${r.source_bytes} byte(s) policy=${r.vault_policy ?? "(none)"} (${r.repo_id})`;
|
|
1112
1117
|
});
|
|
1113
1118
|
return lines.join("\n");
|
|
1114
1119
|
}
|
|
@@ -1178,12 +1183,12 @@ async function view(args) {
|
|
|
1178
1183
|
try {
|
|
1179
1184
|
// Design D3: `view` NEVER passes `refs: true` — it is side-effect-free
|
|
1180
1185
|
// by construction, not by convention. Materialization belongs to `fsck`.
|
|
1181
|
-
const s = await sdk.
|
|
1186
|
+
const s = await sdk.repos.status({ ...target, ...(a.includes("--no-reconcile") ? { reconcile: "deferred" } : {}) });
|
|
1182
1187
|
const isByo = s.vault?.storage_profile === "byo";
|
|
1183
1188
|
let mirror = null;
|
|
1184
1189
|
if (s.repo_id) {
|
|
1185
1190
|
try {
|
|
1186
|
-
mirror = await sdk.
|
|
1191
|
+
mirror = await sdk.repos.mirrorStatus({ ...target, repo_id: s.repo_id, is_byo: isByo });
|
|
1187
1192
|
} catch {
|
|
1188
1193
|
// best-effort — a mirror read failure never fails `view`
|
|
1189
1194
|
}
|
|
@@ -1195,19 +1200,8 @@ async function view(args) {
|
|
|
1195
1200
|
}
|
|
1196
1201
|
const verifyRefsAction = nextAction("verify_refs", { command: "run402 repos fsck", why: "Walk the signed chain and materialize verified refs." });
|
|
1197
1202
|
const combinedNextActions = s.vault ? [verifyRefsAction, ...(s.next_actions ?? [])] : (s.next_actions ?? []);
|
|
1198
|
-
// kygit-handoff design D8 — the mirror of the OLD `npm i -g run402`
|
|
1199
|
-
// bug, pointing the other way: a `kygit::` remote with no
|
|
1200
|
-
// `git-remote-kygit` on PATH fails every push/clone/fetch inside git.
|
|
1201
|
-
let warnings = s.warnings ?? [];
|
|
1202
|
-
if (s.remote?.url?.startsWith("kygit::")) {
|
|
1203
|
-
const { isExecutableOnPath } = await import("./path-lookup.mjs");
|
|
1204
|
-
if (!isExecutableOnPath("git-remote-kygit")) {
|
|
1205
|
-
warnings = [...warnings, { kind: "kygit_helper_missing", message: "this checkout's remote is kygit:: but git-remote-kygit is not on PATH", setup_command: "npm i -g @kychee/kygit" }];
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
1203
|
const out = {
|
|
1209
1204
|
...s,
|
|
1210
|
-
warnings,
|
|
1211
1205
|
refs: { known: false, reason: "not_materialized" },
|
|
1212
1206
|
mirror,
|
|
1213
1207
|
next_actions: combinedNextActions,
|
|
@@ -1230,23 +1224,23 @@ async function view(args) {
|
|
|
1230
1224
|
if (s.messaging_cache_excluded !== null && s.messaging_cache_excluded !== undefined) {
|
|
1231
1225
|
console.error(`messaging cache excluded from git: ${s.messaging_cache_excluded}`);
|
|
1232
1226
|
}
|
|
1233
|
-
//
|
|
1227
|
+
// vault-byo-primary-bucket task 3.5: the no-payload-copy disclosure —
|
|
1234
1228
|
// unconditional and independent of mirror status (D7), never folded
|
|
1235
1229
|
// into the mirror finding below (that's a SEPARATE fact: "is there a
|
|
1236
1230
|
// second copy", not "is there any platform-held copy at all").
|
|
1237
1231
|
if (isByo) {
|
|
1238
|
-
console.error(`storage: byo (${s.vault?.byo_destination ?? "(unknown)"}) — ${
|
|
1239
|
-
console.error(
|
|
1232
|
+
console.error(`storage: byo (${s.vault?.byo_destination ?? "(unknown)"}) — ${VAULT_BYO_HEADLINE_STATEMENT}`);
|
|
1233
|
+
console.error(VAULT_BYO_NO_PAYLOAD_COPY_STATEMENT);
|
|
1240
1234
|
}
|
|
1241
1235
|
if (mirror?.configured) {
|
|
1242
1236
|
const currency = mirror.is_current === true ? "current" : mirror.is_current === false ? `STALE — ${mirror.closing_command}` : "unknown (mirror unreachable or vault unread)";
|
|
1243
1237
|
console.error(`mirror ${mirror.destination}: mirrored generation ${mirror.mirrored_generation ?? "(none)"}, vault newest ${mirror.newest_generation ?? "(none)"} — ${currency}`);
|
|
1244
1238
|
}
|
|
1245
|
-
//
|
|
1239
|
+
// vault-mirror-default: echoed verbatim from the SDK, exactly like the
|
|
1246
1240
|
// vault warnings below — informational, never blocking, and it clears on
|
|
1247
1241
|
// the first successful mirror write or sync.
|
|
1248
1242
|
if (mirror?.finding) console.error(`finding (${mirror.finding.kind}): ${mirror.finding.message} — ${mirror.finding.setup_command}`);
|
|
1249
|
-
for (const w of warnings) console.error(`warning (${w.kind}): ${w.message}${w.setup_command ? ` — ${w.setup_command}` : ""}`);
|
|
1243
|
+
for (const w of s.warnings ?? []) console.error(`warning (${w.kind}): ${w.message}${w.setup_command ? ` — ${w.setup_command}` : ""}`);
|
|
1250
1244
|
for (const n of combinedNextActions) console.error(`next: ${n.why ?? n.action ?? n.type}${n.command ? ` — ${n.command}` : ""}`);
|
|
1251
1245
|
printVerboseStats(a, sdk);
|
|
1252
1246
|
} catch (err) {
|
|
@@ -1272,7 +1266,7 @@ async function rename(args) {
|
|
|
1272
1266
|
let projectId;
|
|
1273
1267
|
if (repoFlag != null) {
|
|
1274
1268
|
try {
|
|
1275
|
-
projectId = (await sdk.
|
|
1269
|
+
projectId = (await sdk.repos.get(repoFlag)).project_id;
|
|
1276
1270
|
} catch (err) {
|
|
1277
1271
|
reportSdkError(err);
|
|
1278
1272
|
return;
|
|
@@ -1286,7 +1280,7 @@ async function rename(args) {
|
|
|
1286
1280
|
try {
|
|
1287
1281
|
const owningOrg = await resolveOwningOrgId(projectId);
|
|
1288
1282
|
const orgSlug = owningOrg ? (await sdk.org(owningOrg).get()).slug : null;
|
|
1289
|
-
if (orgSlug) address =
|
|
1283
|
+
if (orgSlug) address = vaultRemoteUrlForRepo(orgSlug, result.repo_name);
|
|
1290
1284
|
} catch {
|
|
1291
1285
|
// The name is already set — a failed address-preview lookup is never fatal.
|
|
1292
1286
|
}
|
|
@@ -1367,7 +1361,7 @@ async function del(args) {
|
|
|
1367
1361
|
fail({ code: "BAD_USAGE", message: "pass --repo or --project, not both." });
|
|
1368
1362
|
}
|
|
1369
1363
|
try {
|
|
1370
|
-
projectId = (await sdk.
|
|
1364
|
+
projectId = (await sdk.repos.get(repoFlag)).project_id;
|
|
1371
1365
|
} catch (err) {
|
|
1372
1366
|
reportSdkError(err);
|
|
1373
1367
|
return;
|
|
@@ -1381,7 +1375,7 @@ async function del(args) {
|
|
|
1381
1375
|
|
|
1382
1376
|
let status;
|
|
1383
1377
|
try {
|
|
1384
|
-
status = await sdk.
|
|
1378
|
+
status = await sdk.repos.status({ project_id: projectId });
|
|
1385
1379
|
} catch (err) {
|
|
1386
1380
|
reportSdkError(err);
|
|
1387
1381
|
return;
|
|
@@ -1435,21 +1429,21 @@ async function del(args) {
|
|
|
1435
1429
|
}
|
|
1436
1430
|
}
|
|
1437
1431
|
|
|
1438
|
-
// ───
|
|
1432
|
+
// ─── capture ────────────────────────────────────────────────────────────────
|
|
1439
1433
|
|
|
1440
|
-
const
|
|
1434
|
+
const CAPTURE_VALUE_FLAGS = [...COMMON_VALUE_FLAGS, "--message", "--manifest-out"];
|
|
1441
1435
|
|
|
1442
1436
|
/**
|
|
1443
1437
|
* When neither `--repo` nor `--project` was given explicitly, look at the
|
|
1444
1438
|
* local `run402`/`origin` remote and, if it is a SLUG-form address
|
|
1445
|
-
* (`run402::<org-slug>/<name>`), return the parsed address so `
|
|
1439
|
+
* (`run402::<org-slug>/<name>`), return the parsed address so `capture`
|
|
1446
1440
|
* can push-to-create through it — the same address-form resolution
|
|
1447
1441
|
* `git push` drives via the remote helper.
|
|
1448
1442
|
*/
|
|
1449
1443
|
async function detectSlugFormRemote(a, repoDir) {
|
|
1450
1444
|
if (flagValue(a, "--repo") != null || flagValue(a, "--project") != null) return null;
|
|
1451
1445
|
const { hardenedGit } = await import("#sdk/node");
|
|
1452
|
-
const {
|
|
1446
|
+
const { parseVaultRemoteUrl, vaultRemoteAddressForm } = await import("#sdk");
|
|
1453
1447
|
for (const name of ["run402", "origin"]) {
|
|
1454
1448
|
let url;
|
|
1455
1449
|
try {
|
|
@@ -1458,8 +1452,13 @@ async function detectSlugFormRemote(a, repoDir) {
|
|
|
1458
1452
|
continue;
|
|
1459
1453
|
}
|
|
1460
1454
|
if (!url) continue;
|
|
1461
|
-
|
|
1462
|
-
|
|
1455
|
+
let address;
|
|
1456
|
+
try {
|
|
1457
|
+
address = parseVaultRemoteUrl(url);
|
|
1458
|
+
} catch {
|
|
1459
|
+
continue; // another scheme's remote — not a vault address
|
|
1460
|
+
}
|
|
1461
|
+
if (address && vaultRemoteAddressForm(address) === "slug") return address;
|
|
1463
1462
|
}
|
|
1464
1463
|
return null;
|
|
1465
1464
|
}
|
|
@@ -1505,7 +1504,7 @@ const SNAPSHOT_CHANGED_PATHS_CAP = 200;
|
|
|
1505
1504
|
* captured_digest, top_level, global_excludes_path — stay). `verbose`
|
|
1506
1505
|
* restores them (composes with the summary fields, does not replace
|
|
1507
1506
|
* them) — the `-v`/`--verbose` flag already means "print a stats
|
|
1508
|
-
* line"; on `
|
|
1507
|
+
* line"; on `capture --dry-run`/`capture` it ALSO inlines the full
|
|
1509
1508
|
* inventory.
|
|
1510
1509
|
* - `manifest_path` is `null` unless `--manifest-out <path>` wrote the
|
|
1511
1510
|
* COMPLETE, untouched payload to that file — see `writeManifestOut`.
|
|
@@ -1537,17 +1536,17 @@ function writeManifestOut(path, payload) {
|
|
|
1537
1536
|
} catch (e) {
|
|
1538
1537
|
fail({
|
|
1539
1538
|
code: "MANIFEST_OUT_WRITE_FAILED",
|
|
1540
|
-
message: `could not write the full
|
|
1539
|
+
message: `could not write the full captured-file inventory to ${path}: ${e instanceof Error ? e.message : String(e)}`,
|
|
1541
1540
|
hint: "Check that the path is writable and its parent directory exists.",
|
|
1542
1541
|
details: { path },
|
|
1543
1542
|
});
|
|
1544
1543
|
}
|
|
1545
1544
|
}
|
|
1546
1545
|
|
|
1547
|
-
async function
|
|
1546
|
+
async function capture(args) {
|
|
1548
1547
|
const a = normalizeArgv(args);
|
|
1549
|
-
assertKnownFlags(a, [...
|
|
1550
|
-
requirePositionalCount(a,
|
|
1548
|
+
assertKnownFlags(a, [...CAPTURE_VALUE_FLAGS, "--checkpoint", "--dry-run", "--allow-dirty", "-v", "--verbose", "--help", "-h"], CAPTURE_VALUE_FLAGS);
|
|
1549
|
+
requirePositionalCount(a, CAPTURE_VALUE_FLAGS, { min: 0, max: 0, command: "run402 repos capture", missing: "" });
|
|
1551
1550
|
const sdk = getSdk();
|
|
1552
1551
|
const dryRun = a.includes("--dry-run");
|
|
1553
1552
|
const message = flagValue(a, "--message");
|
|
@@ -1565,9 +1564,9 @@ async function snapshot(args) {
|
|
|
1565
1564
|
console.error("");
|
|
1566
1565
|
console.error(`repo allocated (genesis ${created.genesis_sha256}) — one-shot recovery receipt, keep many copies:`);
|
|
1567
1566
|
console.error(JSON.stringify(created.recovery_receipt));
|
|
1568
|
-
//
|
|
1567
|
+
// vault-mirror-default: lazy allocation is a birth too — the mirror
|
|
1569
1568
|
// one-liner rides beside the recovery receipt here as well.
|
|
1570
|
-
console.error(
|
|
1569
|
+
console.error(VAULT_MIRROR_SETUP_HINT);
|
|
1571
1570
|
await printKeystoreLocation();
|
|
1572
1571
|
console.error("");
|
|
1573
1572
|
},
|
|
@@ -1581,11 +1580,11 @@ async function snapshot(args) {
|
|
|
1581
1580
|
const verbose = isVerbose(a);
|
|
1582
1581
|
try {
|
|
1583
1582
|
if (dryRun) {
|
|
1584
|
-
const plan = await sdk.
|
|
1583
|
+
const plan = await sdk.repos.planCapture(opts);
|
|
1585
1584
|
if (manifestOutPath != null) writeManifestOut(manifestOutPath, plan);
|
|
1586
1585
|
printJson(sdk, summarizeSnapshotPayload(plan, { verbose, manifestPath: manifestOutPath }));
|
|
1587
1586
|
if (plan.allocation_needed) {
|
|
1588
|
-
console.error("dry-run: no repo allocated for this project yet — a real
|
|
1587
|
+
console.error("dry-run: no repo allocated for this project yet — a real capture would allocate one first; object/byte sizing is not knowable until then");
|
|
1589
1588
|
} else {
|
|
1590
1589
|
console.error(
|
|
1591
1590
|
`dry-run: would publish generation ${plan.would_admit_generation} (${plan.would_admit_generation_decimal}, ${plan.form}) — ` +
|
|
@@ -1596,7 +1595,7 @@ async function snapshot(args) {
|
|
|
1596
1595
|
printVerboseStats(a, sdk);
|
|
1597
1596
|
return;
|
|
1598
1597
|
}
|
|
1599
|
-
const result = await sdk.
|
|
1598
|
+
const result = await sdk.repos.capture(opts);
|
|
1600
1599
|
if (manifestOutPath != null) writeManifestOut(manifestOutPath, result);
|
|
1601
1600
|
// Snapshot-only vault (no branch head published): a plain `git clone`
|
|
1602
1601
|
// of this vault prints "cloned an empty repository" with no hint the
|
|
@@ -1604,7 +1603,7 @@ async function snapshot(args) {
|
|
|
1604
1603
|
const resultRefNames = Object.keys(result.refs ?? {});
|
|
1605
1604
|
const snapshotOnly = resultRefNames.length > 0 && !resultRefNames.some((r) => r.startsWith("refs/heads/"));
|
|
1606
1605
|
const payload = summarizeSnapshotPayload(result, { verbose, manifestPath: manifestOutPath });
|
|
1607
|
-
//
|
|
1606
|
+
// vault-clone-scaling (P3): advisory only — the SDK computed the
|
|
1608
1607
|
// staleness from locally-learned coverage; this entry never gates.
|
|
1609
1608
|
if (result.checkpoint_staleness?.advised) {
|
|
1610
1609
|
payload.next_actions = [
|
|
@@ -1621,19 +1620,19 @@ async function snapshot(args) {
|
|
|
1621
1620
|
payload.next_actions = [
|
|
1622
1621
|
...(payload.next_actions ?? []),
|
|
1623
1622
|
{
|
|
1624
|
-
type: "
|
|
1623
|
+
type: "restore_capture_ref",
|
|
1625
1624
|
command: `git fetch <remote> '+${snapRef}:${snapRef}' && git checkout -b restored ${snapRef}`,
|
|
1626
|
-
why: `This vault has no branch heads — a plain \`git clone\` will report an empty repository. The
|
|
1625
|
+
why: `This vault has no branch heads — a plain \`git clone\` will report an empty repository. The captured history lives on ${snapRef}; \`git push\` a branch to make plain clones work.`,
|
|
1627
1626
|
},
|
|
1628
1627
|
];
|
|
1629
1628
|
}
|
|
1630
1629
|
printJson(sdk, payload);
|
|
1631
1630
|
console.error(`published generation ${result.generation} (${result.form})`);
|
|
1632
|
-
if (snapshotOnly) console.error(`note: no branch heads in this vault — a plain clone looks empty;
|
|
1631
|
+
if (snapshotOnly) console.error(`note: no branch heads in this vault — a plain clone looks empty; captured history is on ${resultRefNames.sort()[0]} (see next_actions)`);
|
|
1633
1632
|
if (result.mirror_push?.outcome === "pushed") {
|
|
1634
1633
|
console.error(`mirror: pushed generation ${result.generation} (${result.mirror_push.summary?.objects_copied ?? 0} object(s) copied)`);
|
|
1635
1634
|
} else if (result.mirror_push?.outcome === "failed") {
|
|
1636
|
-
console.error(`mirror:
|
|
1635
|
+
console.error(`mirror: mirroring this capture FAILED (deploy is unaffected) — ${result.mirror_push.error ?? "see mirror_push.summary.errors"}`);
|
|
1637
1636
|
}
|
|
1638
1637
|
printDirtyDisclosure(result.snapshot);
|
|
1639
1638
|
printVerboseStats(a, sdk);
|
|
@@ -1772,7 +1771,7 @@ async function handoff(args) {
|
|
|
1772
1771
|
if (a.includes("--list")) {
|
|
1773
1772
|
const target = await vaultTarget(a);
|
|
1774
1773
|
try {
|
|
1775
|
-
const result = await sdk.
|
|
1774
|
+
const result = await sdk.repos.listHandoffs(target);
|
|
1776
1775
|
printJson(sdk, result);
|
|
1777
1776
|
printVerboseStats(a, sdk);
|
|
1778
1777
|
} catch (err) {
|
|
@@ -1784,7 +1783,7 @@ async function handoff(args) {
|
|
|
1784
1783
|
if (revokeId != null) {
|
|
1785
1784
|
const target = await vaultTarget(a);
|
|
1786
1785
|
try {
|
|
1787
|
-
const result = await sdk.
|
|
1786
|
+
const result = await sdk.repos.revokeHandoff(revokeId, target);
|
|
1788
1787
|
printJson(sdk, result);
|
|
1789
1788
|
printVerboseStats(a, sdk);
|
|
1790
1789
|
} catch (err) {
|
|
@@ -1809,18 +1808,18 @@ async function handoff(args) {
|
|
|
1809
1808
|
onCommitLine: (line) => console.error(line),
|
|
1810
1809
|
};
|
|
1811
1810
|
try {
|
|
1812
|
-
const result = await sdk.
|
|
1811
|
+
const result = await sdk.repos.handoff(opts);
|
|
1813
1812
|
for (const w of result.warnings ?? []) {
|
|
1814
1813
|
console.error(w.message ?? `${w.code}`);
|
|
1815
1814
|
}
|
|
1816
1815
|
console.error(`handoff minted: role ${result.minted_role}, expires ${result.expires_at}`);
|
|
1817
|
-
//
|
|
1816
|
+
// vault-multi-writer (rev 47) task 6.4 — a handoff is now also a
|
|
1818
1817
|
// WRITER admission, not just a checkout pass: the recipient signs its
|
|
1819
1818
|
// own future pushes with a NEW key this vault's chain recognizes as a
|
|
1820
1819
|
// writer the moment `resume` redeems it (design D4 — a grant minted here,
|
|
1821
1820
|
// a two-signature acceptance the recipient's own resume completes).
|
|
1822
1821
|
console.error(`the recipient becomes a WRITER on this vault the moment they resume — their own key signs future pushes, not yours.`);
|
|
1823
|
-
console.error(`recipient runs:
|
|
1822
|
+
console.error(`recipient runs: run402 repos resume <key printed below>`);
|
|
1824
1823
|
if (asJson) {
|
|
1825
1824
|
printJson(sdk, result);
|
|
1826
1825
|
} else {
|
|
@@ -1948,7 +1947,7 @@ async function resume(args) {
|
|
|
1948
1947
|
// `--no-init` opts out entirely.
|
|
1949
1948
|
const coldStart = a.includes("--no-init") ? { performed: false, skipped: "no_init" } : await foldColdStartForResume(sdk);
|
|
1950
1949
|
try {
|
|
1951
|
-
const result = await sdk.
|
|
1950
|
+
const result = await sdk.repos.resume({ key, ...(to != null ? { to } : {}), onLine: (line) => console.error(line) });
|
|
1952
1951
|
if (coldStart.next_action) result.next_actions = [...(result.next_actions ?? []), coldStart.next_action];
|
|
1953
1952
|
// The restored checkout's first git command needs the remote helper on
|
|
1954
1953
|
// PATH; an npx-run resume/join has it only in the npx cache. Name it.
|
|
@@ -1966,7 +1965,7 @@ async function resume(args) {
|
|
|
1966
1965
|
}
|
|
1967
1966
|
console.error("");
|
|
1968
1967
|
console.error(`resumed into ${result.restored.dir} (branch ${result.restored.branch})`);
|
|
1969
|
-
//
|
|
1968
|
+
// vault-multi-writer (rev 47) task 6.4 — this checkout's own writer
|
|
1970
1969
|
// activation (design D5): the outcome is "active" either way, whether
|
|
1971
1970
|
// this call submitted a fresh activation head or a prior attempt's
|
|
1972
1971
|
// already landed (crash-resumable, task 5.6's own idempotent-skip).
|
|
@@ -2007,7 +2006,7 @@ async function invite(args) {
|
|
|
2007
2006
|
if (a.includes("--list")) {
|
|
2008
2007
|
const target = await vaultTarget(a);
|
|
2009
2008
|
try {
|
|
2010
|
-
const result = await sdk.
|
|
2009
|
+
const result = await sdk.repos.listInvites(target);
|
|
2011
2010
|
printJson(sdk, result);
|
|
2012
2011
|
printVerboseStats(a, sdk);
|
|
2013
2012
|
} catch (err) {
|
|
@@ -2019,7 +2018,7 @@ async function invite(args) {
|
|
|
2019
2018
|
if (revokeId != null) {
|
|
2020
2019
|
const target = await vaultTarget(a);
|
|
2021
2020
|
try {
|
|
2022
|
-
const result = await sdk.
|
|
2021
|
+
const result = await sdk.repos.revokeInvite(revokeId, target);
|
|
2023
2022
|
printJson(sdk, result);
|
|
2024
2023
|
printVerboseStats(a, sdk);
|
|
2025
2024
|
} catch (err) {
|
|
@@ -2060,12 +2059,12 @@ async function invite(args) {
|
|
|
2060
2059
|
onCommitLine: (line) => console.error(line),
|
|
2061
2060
|
};
|
|
2062
2061
|
try {
|
|
2063
|
-
const result = await sdk.
|
|
2062
|
+
const result = await sdk.repos.invite(opts);
|
|
2064
2063
|
for (const w of result.warnings ?? []) {
|
|
2065
2064
|
console.error(w.message ?? `${w.code}`);
|
|
2066
2065
|
}
|
|
2067
2066
|
console.error(`invite minted: role ${result.minted_role}, expires ${result.expires_at}, room ${result.room?.room_key ?? "(unknown)"}`);
|
|
2068
|
-
console.error(`recipient runs:
|
|
2067
|
+
console.error(`recipient runs: run402 repos join <key printed below>`);
|
|
2069
2068
|
if (result.inviter_presence && result.inviter_presence.registered === false) {
|
|
2070
2069
|
console.error(`note: your own presence was not registered (${result.inviter_presence.error}) — the invite still mints and can be redeemed`);
|
|
2071
2070
|
}
|
|
@@ -2120,7 +2119,7 @@ async function joinInvite(args) {
|
|
|
2120
2119
|
const { key: sessionKey, source: sessionKeySource } = resolveSessionKey();
|
|
2121
2120
|
const { task } = await resolveTaskLabel({});
|
|
2122
2121
|
try {
|
|
2123
|
-
const result = await sdk.
|
|
2122
|
+
const result = await sdk.repos.join({
|
|
2124
2123
|
key,
|
|
2125
2124
|
...(to != null ? { to } : {}),
|
|
2126
2125
|
...(program ? { program } : {}),
|
|
@@ -2167,7 +2166,7 @@ async function joinInvite(args) {
|
|
|
2167
2166
|
console.error("");
|
|
2168
2167
|
console.error(`joined into ${result.restored.dir} (branch ${result.restored.branch})`);
|
|
2169
2168
|
if (result.deduplicated) console.error("note: this key was already redeemed by this same principal — the ORIGINAL envelope was reused (safe replay)");
|
|
2170
|
-
//
|
|
2169
|
+
// vault-multi-writer (rev 47) / kygit-invite design D5 — this
|
|
2171
2170
|
// checkout's own writer activation, printed in the SAME `writer: …`
|
|
2172
2171
|
// shape `resume` uses. `pending` is D9's not-stranded path: the key is
|
|
2173
2172
|
// a pending writer, and the `request_writer_sync` next action below
|
|
@@ -2211,7 +2210,7 @@ async function joinInvite(args) {
|
|
|
2211
2210
|
// ─── policy ─────────────────────────────────────────────────────────────────
|
|
2212
2211
|
|
|
2213
2212
|
/**
|
|
2214
|
-
*
|
|
2213
|
+
* vault-checkpoint-cadence design D1: `auto-gc` is a LOCAL, per-checkout
|
|
2215
2214
|
* knob — the same local-git-config mechanism as the restore marker, and the
|
|
2216
2215
|
* same shape as git's own `gc.auto` — deliberately NOT a gateway call like
|
|
2217
2216
|
* `required`/`grandfathered` above (there is no server-side policy row for
|
|
@@ -2221,7 +2220,7 @@ async function joinInvite(args) {
|
|
|
2221
2220
|
* `off` is sugar for `0` (disables auto-gc entirely).
|
|
2222
2221
|
*/
|
|
2223
2222
|
async function policyAutoGc(rawValue, a) {
|
|
2224
|
-
const { hardenedGit,
|
|
2223
|
+
const { hardenedGit, readVaultAutoGcThreshold, writeVaultAutoGcThreshold, VAULT_AUTO_GC_GENERATIONS_DEFAULT } = await import("#sdk/node");
|
|
2225
2224
|
const dir = process.cwd();
|
|
2226
2225
|
try {
|
|
2227
2226
|
await hardenedGit(dir, ["rev-parse", "--git-dir"]);
|
|
@@ -2234,12 +2233,12 @@ async function policyAutoGc(rawValue, a) {
|
|
|
2234
2233
|
}
|
|
2235
2234
|
const sdk = getSdk();
|
|
2236
2235
|
if (rawValue === undefined) {
|
|
2237
|
-
const current = await
|
|
2238
|
-
printJson(sdk, { auto_gc_generations: current, default:
|
|
2236
|
+
const current = await readVaultAutoGcThreshold(dir);
|
|
2237
|
+
printJson(sdk, { auto_gc_generations: current, default: VAULT_AUTO_GC_GENERATIONS_DEFAULT });
|
|
2239
2238
|
console.error(
|
|
2240
2239
|
current === 0
|
|
2241
2240
|
? "auto-gc is disabled for this checkout"
|
|
2242
|
-
: `auto-gc runs after a push once ${current} generation(s) have accumulated since the last checkpoint (default ${
|
|
2241
|
+
: `auto-gc runs after a push once ${current} generation(s) have accumulated since the last checkpoint (default ${VAULT_AUTO_GC_GENERATIONS_DEFAULT})`,
|
|
2243
2242
|
);
|
|
2244
2243
|
printVerboseStats(a, sdk);
|
|
2245
2244
|
return;
|
|
@@ -2257,7 +2256,7 @@ async function policyAutoGc(rawValue, a) {
|
|
|
2257
2256
|
details: { value: rawValue },
|
|
2258
2257
|
});
|
|
2259
2258
|
}
|
|
2260
|
-
await
|
|
2259
|
+
await writeVaultAutoGcThreshold(dir, generations);
|
|
2261
2260
|
printJson(sdk, { auto_gc_generations: generations });
|
|
2262
2261
|
console.error(
|
|
2263
2262
|
generations === 0
|
|
@@ -2303,13 +2302,13 @@ async function policy(args) {
|
|
|
2303
2302
|
const target = await vaultTarget(a);
|
|
2304
2303
|
try {
|
|
2305
2304
|
const sdk = getSdk();
|
|
2306
|
-
const repoId = target.repo_id ?? (await sdk.
|
|
2307
|
-
const result = await sdk.
|
|
2305
|
+
const repoId = target.repo_id ?? (await sdk.repos.forProject(target.project_id)).repo_id;
|
|
2306
|
+
const result = await sdk.repos.setPolicy(repoId, { vault_policy: requested, ...(reason != null ? { reason } : {}) });
|
|
2308
2307
|
printJson(sdk, { repo_id: repoId, ...result });
|
|
2309
2308
|
console.error(
|
|
2310
2309
|
result.changed
|
|
2311
|
-
? `
|
|
2312
|
-
: `
|
|
2310
|
+
? `vault_policy is now ${result.vault_policy} (version ${result.vault_policy_version})`
|
|
2311
|
+
: `vault_policy was already ${result.vault_policy} — nothing changed`,
|
|
2313
2312
|
);
|
|
2314
2313
|
for (const w of result.warnings ?? []) console.error(`warning (${w.kind}): ${w.message}`);
|
|
2315
2314
|
printVerboseStats(a, sdk);
|
|
@@ -2325,7 +2324,7 @@ const MIRROR_VALUE_FLAGS = [...COMMON_VALUE_FLAGS, "--profile", "--region", "--e
|
|
|
2325
2324
|
async function mirrorRead(target, a) {
|
|
2326
2325
|
const sdk = getSdk();
|
|
2327
2326
|
try {
|
|
2328
|
-
const result = await sdk.
|
|
2327
|
+
const result = await sdk.repos.mirrorStatus(target);
|
|
2329
2328
|
printJson(sdk, result);
|
|
2330
2329
|
if (!result.configured) {
|
|
2331
2330
|
console.error(`no mirror configured for ${result.repo_id}. Configure one: run402 repos mirror <destination>`);
|
|
@@ -2346,7 +2345,7 @@ async function mirrorSet(target, destination, a) {
|
|
|
2346
2345
|
const region = flagValue(a, "--region");
|
|
2347
2346
|
const endpoint = flagValue(a, "--endpoint");
|
|
2348
2347
|
try {
|
|
2349
|
-
const result = await sdk.
|
|
2348
|
+
const result = await sdk.repos.mirrorSet({
|
|
2350
2349
|
...target,
|
|
2351
2350
|
destination_url: destination,
|
|
2352
2351
|
...(credential ? { credential } : {}),
|
|
@@ -2355,7 +2354,7 @@ async function mirrorSet(target, destination, a) {
|
|
|
2355
2354
|
});
|
|
2356
2355
|
printJson(sdk, result);
|
|
2357
2356
|
console.error(`mirror configured for ${result.repo_id} -> ${formatMirrorDestination(result.destination)}`);
|
|
2358
|
-
console.error("run `run402 repos mirror --backfill` to catch it up now, then every
|
|
2357
|
+
console.error("run `run402 repos mirror --backfill` to catch it up now, then every later capture is mirrored automatically.");
|
|
2359
2358
|
printVerboseStats(a, sdk);
|
|
2360
2359
|
} catch (err) {
|
|
2361
2360
|
reportSdkError(err);
|
|
@@ -2365,7 +2364,7 @@ async function mirrorSet(target, destination, a) {
|
|
|
2365
2364
|
async function mirrorOff(target, a) {
|
|
2366
2365
|
const sdk = getSdk();
|
|
2367
2366
|
try {
|
|
2368
|
-
const result = await sdk.
|
|
2367
|
+
const result = await sdk.repos.mirrorRemove(target);
|
|
2369
2368
|
printJson(sdk, result);
|
|
2370
2369
|
console.error(
|
|
2371
2370
|
result.removed
|
|
@@ -2381,7 +2380,7 @@ async function mirrorOff(target, a) {
|
|
|
2381
2380
|
async function mirrorBackfill(target, a) {
|
|
2382
2381
|
const sdk = getSdk();
|
|
2383
2382
|
try {
|
|
2384
|
-
const result = await sdk.
|
|
2383
|
+
const result = await sdk.repos.mirrorSync(target);
|
|
2385
2384
|
printJson(sdk, result);
|
|
2386
2385
|
await spillIfLarge(result.repo_id, "mirror-backfill", result);
|
|
2387
2386
|
console.error(
|
|
@@ -2439,12 +2438,12 @@ function formatOpenProofLine(openProof) {
|
|
|
2439
2438
|
}
|
|
2440
2439
|
|
|
2441
2440
|
/**
|
|
2442
|
-
*
|
|
2441
|
+
* vault-byo-primary-bucket task 3.3: one line reporting `fsck`'s BYO
|
|
2443
2442
|
* presence check — always present for a BYO vault (never blank), absent for
|
|
2444
2443
|
* a managed one (`result.byo_presence` is `undefined` there, so this
|
|
2445
2444
|
* returns `null` and no line prints — zero output change for managed
|
|
2446
2445
|
* vaults). A MISSING-object verdict never reaches here: it throws
|
|
2447
|
-
* `
|
|
2446
|
+
* `VAULT_BYO_OBJECT_MISSING` before `fsck` returns a result at all, so
|
|
2448
2447
|
* this line only ever reports the two non-failure outcomes — checked-clean
|
|
2449
2448
|
* or explicitly not-checked. Shared by `--human` and the default JSON-mode
|
|
2450
2449
|
* stderr summary, same convention as `formatOpenProofLine` above.
|
|
@@ -2514,7 +2513,7 @@ async function fsck(args) {
|
|
|
2514
2513
|
const write = !a.includes("--no-write");
|
|
2515
2514
|
const mirrorRequested = a.includes("--mirror");
|
|
2516
2515
|
try {
|
|
2517
|
-
const result = await sdk.
|
|
2516
|
+
const result = await sdk.repos.fsck({ ...target, write, mirror: mirrorRequested });
|
|
2518
2517
|
if (human) {
|
|
2519
2518
|
console.log(formatFsckHuman(result, mirrorRequested));
|
|
2520
2519
|
if (mirrorRequested && result.mirror) printMirrorHonesty(result.mirror);
|
|
@@ -2552,11 +2551,11 @@ async function fsck(args) {
|
|
|
2552
2551
|
// status as a mirror probe's failure would be).
|
|
2553
2552
|
const openProofLine = formatOpenProofLine(result.open_proof);
|
|
2554
2553
|
if (openProofLine) console.error(openProofLine);
|
|
2555
|
-
//
|
|
2554
|
+
// vault-byo-primary-bucket task 3.3: absent (formats to `null`) for a
|
|
2556
2555
|
// managed vault — `result.byo_presence` is `undefined` there, so this
|
|
2557
2556
|
// line never prints and JSON-mode output for a managed vault is
|
|
2558
2557
|
// unchanged. A missing-object verdict never reaches this line at all —
|
|
2559
|
-
// it throws `
|
|
2558
|
+
// it throws `VAULT_BYO_OBJECT_MISSING` before `fsck` returns, caught
|
|
2560
2559
|
// by this function's own `reportSdkError(err)` below.
|
|
2561
2560
|
const byoPresenceLine = formatByoPresenceLine(result.byo_presence);
|
|
2562
2561
|
if (byoPresenceLine) console.error(byoPresenceLine);
|
|
@@ -2565,7 +2564,7 @@ async function fsck(args) {
|
|
|
2565
2564
|
if (result.mirror.data_loss_detected) {
|
|
2566
2565
|
console.error(`DATA LOSS DETECTED: ${result.mirror.absences.filter((x) => x.adjudication === "unexplained_absence").length} object(s) are unexplained absences.`);
|
|
2567
2566
|
}
|
|
2568
|
-
//
|
|
2567
|
+
// vault-recovery-custody: member recovery-bundle sidecars, reported
|
|
2569
2568
|
// as UNVERIFIED availability hints — nothing about them is chain-
|
|
2570
2569
|
// authenticated; they only say bundle + source recovery code can
|
|
2571
2570
|
// recover this mirror with no server.
|
|
@@ -2593,7 +2592,7 @@ const GC_VALUE_FLAGS = [...COMMON_VALUE_FLAGS, "--intent-core", "--verifier-rece
|
|
|
2593
2592
|
/**
|
|
2594
2593
|
* One line of headroom disclosure. Printed whether or not things fit: a
|
|
2595
2594
|
* person deciding when to compact wants the numbers in the passing case too
|
|
2596
|
-
* (
|
|
2595
|
+
* (vault-compaction-headroom-preflight D4).
|
|
2597
2596
|
*/
|
|
2598
2597
|
function printHeadroomNote(headroom) {
|
|
2599
2598
|
if (!headroom) return;
|
|
@@ -2629,11 +2628,11 @@ async function gc(args) {
|
|
|
2629
2628
|
fail({ code: "BAD_USAGE", message: "--intent-core / --verifier-receipt only apply with --submit.", hint: "Add --submit, or drop the flags to plan." });
|
|
2630
2629
|
}
|
|
2631
2630
|
const target = await vaultTarget(a);
|
|
2632
|
-
//
|
|
2631
|
+
// vault-client-round-trips design D3 (task 4.2): re-apply the local
|
|
2633
2632
|
// object cache's eviction window as a periodic backstop. Best-effort —
|
|
2634
2633
|
// a sweep failure must never block the actual gc plan/submit.
|
|
2635
2634
|
try {
|
|
2636
|
-
await sdk.
|
|
2635
|
+
await sdk.repos.sweepObjectCache(target);
|
|
2637
2636
|
} catch {
|
|
2638
2637
|
// never let cache housekeeping fail a real gc operation
|
|
2639
2638
|
}
|
|
@@ -2642,11 +2641,11 @@ async function gc(args) {
|
|
|
2642
2641
|
if (submitting) {
|
|
2643
2642
|
const opts = { ...target, submit: { core: readJsonFile("--intent-core", corePath), verifier_receipt: readJsonFile("--verifier-receipt", receiptPath) } };
|
|
2644
2643
|
if (a.includes("--wait")) opts.submit.wait = {};
|
|
2645
|
-
const prune = await sdk.
|
|
2644
|
+
const prune = await sdk.repos.prune(opts);
|
|
2646
2645
|
// No compaction runs on this half, so the figures come from the
|
|
2647
2646
|
// standalone read — disclosed anyway, because "how close is this org to
|
|
2648
2647
|
// its pooled cap" is exactly as worth knowing while reclaiming storage.
|
|
2649
|
-
const headroom = await sdk.
|
|
2648
|
+
const headroom = await sdk.repos.compactHeadroom(target).catch(() => null);
|
|
2650
2649
|
const out = { phase: "submitted", prune, headroom };
|
|
2651
2650
|
printJson(sdk, out);
|
|
2652
2651
|
if (prune.confirmation?.outcome) {
|
|
@@ -2664,8 +2663,8 @@ async function gc(args) {
|
|
|
2664
2663
|
return;
|
|
2665
2664
|
}
|
|
2666
2665
|
|
|
2667
|
-
const checkpoint = await sdk.
|
|
2668
|
-
const prune = await sdk.
|
|
2666
|
+
const checkpoint = await sdk.repos.compact({ ...target, ...(a.includes("--force-headroom") ? { ignoreHeadroom: true } : {}) });
|
|
2667
|
+
const prune = await sdk.repos.prune(target);
|
|
2669
2668
|
const nextActions = [];
|
|
2670
2669
|
if (!prune.blocked_reason && prune.object_candidates.length > 0) {
|
|
2671
2670
|
// Additive fields beyond the CLI's usual {type, command, why}: the
|
|
@@ -2757,8 +2756,8 @@ async function accessRead(args) {
|
|
|
2757
2756
|
const sdk = getSdk();
|
|
2758
2757
|
const target = await vaultTarget(a);
|
|
2759
2758
|
try {
|
|
2760
|
-
const result = await sdk.
|
|
2761
|
-
//
|
|
2759
|
+
const result = await sdk.repos.access({ ...target, ...(a.includes("--no-reconcile") ? { reconcile: "deferred" } : {}) });
|
|
2760
|
+
// vault-recovery-custody — the "you" block: YOUR OWN wrapper custody
|
|
2762
2761
|
// (kind/state per wrapper, custody scheme), rendered inside the family's
|
|
2763
2762
|
// custody roster read. Principal-scoped, so it needs your control-plane
|
|
2764
2763
|
// (human) session; without one it is honestly absent-with-reason rather
|
|
@@ -2822,9 +2821,9 @@ const ROTATION_VALUE_FLAGS = [...COMMON_VALUE_FLAGS, "--recipient-state-version"
|
|
|
2822
2821
|
* `--recipient-state-version`/`--recipient-revocation-version` are the D194
|
|
2823
2822
|
* frozen watermarks this attempt must be fenced against. They are NOT
|
|
2824
2823
|
* discovered automatically here: the live gateway exposes NO general read
|
|
2825
|
-
* route for `internal.
|
|
2824
|
+
* route for `internal.vault_recipient_state_counters` outside the
|
|
2826
2825
|
* `key-revocation` declare route's own response (see
|
|
2827
|
-
* `
|
|
2826
|
+
* `Vault.rotateEpoch`'s doc comment, `sdk/src/node/vault-
|
|
2828
2827
|
* publication.ts`, for the confirmed source-level finding). Until that
|
|
2829
2828
|
* route ships, this verb needs the pair supplied explicitly — refusing
|
|
2830
2829
|
* cleanly and naming exactly this when they are omitted, rather than
|
|
@@ -2859,7 +2858,7 @@ async function accessRepair(args) {
|
|
|
2859
2858
|
const sdk = getSdk();
|
|
2860
2859
|
const target = await vaultTarget(a);
|
|
2861
2860
|
try {
|
|
2862
|
-
const result = await sdk.
|
|
2861
|
+
const result = await sdk.repos.rotateEpoch({
|
|
2863
2862
|
...target,
|
|
2864
2863
|
reason: "elective_rekey",
|
|
2865
2864
|
recipient_state_version: recipientStateVersion,
|
|
@@ -2894,7 +2893,7 @@ async function accessRevokeKey(args) {
|
|
|
2894
2893
|
const sdk = getSdk();
|
|
2895
2894
|
const target = await vaultTarget(a);
|
|
2896
2895
|
try {
|
|
2897
|
-
const result = await sdk.
|
|
2896
|
+
const result = await sdk.repos.rotateEpochForKeyRevocation(principalId, {
|
|
2898
2897
|
...target,
|
|
2899
2898
|
...(flagValue(a, "--idempotency-key") != null ? { client_idempotency_key: flagValue(a, "--idempotency-key") } : {}),
|
|
2900
2899
|
});
|
|
@@ -2926,21 +2925,21 @@ async function accessRevokeKey(args) {
|
|
|
2926
2925
|
* separately — that call is itself an ORDINARY admission and is itself
|
|
2927
2926
|
* refused `EPOCH_ROTATION_REQUIRED` for as long as this declaration stays
|
|
2928
2927
|
* outstanding. Pass the receipt
|
|
2929
|
-
* to `r.
|
|
2928
|
+
* to `r.repos.rotateEpoch({..., pending_confirmations: [{principal_id,
|
|
2930
2929
|
* ek_fingerprint, receipt}]})` instead — it rides the SAME head as the
|
|
2931
2930
|
* rotation this declaration requires, publishing durably without needing a
|
|
2932
|
-
* second, separately-gated admission. See `
|
|
2931
|
+
* second, separately-gated admission. See `Vault.rotateEpoch`'s
|
|
2933
2932
|
* doc comment for what this does NOT do: the folded principal is still
|
|
2934
2933
|
* excluded from THIS rotation's own envelope set (D196) and becomes
|
|
2935
2934
|
* eligible starting at the NEXT rotation.
|
|
2936
2935
|
*/
|
|
2937
2936
|
/**
|
|
2938
2937
|
* `repos access repin --principal <principal_id> --fingerprint <ek_…>` — a KEY-HOLDER
|
|
2939
|
-
* explicitly accepts a recipient's CHANGED key (
|
|
2938
|
+
* explicitly accepts a recipient's CHANGED key (vault-agent-envelopes D3).
|
|
2940
2939
|
* The session-start reconcile refuses `pinned_key_mismatch` and never
|
|
2941
2940
|
* bypasses it, not even after an owner's revoke — acceptance names the new
|
|
2942
2941
|
* fingerprint (the out-of-band verification point) and moves the local pin.
|
|
2943
|
-
* Adapter only: `sdk.
|
|
2942
|
+
* Adapter only: `sdk.repos.acceptRecipientKeyChange`.
|
|
2944
2943
|
*/
|
|
2945
2944
|
async function accessRepin(args) {
|
|
2946
2945
|
const a = normalizeArgv(args);
|
|
@@ -2954,8 +2953,8 @@ async function accessRepin(args) {
|
|
|
2954
2953
|
const sdk = getSdk();
|
|
2955
2954
|
const target = await vaultTarget(a);
|
|
2956
2955
|
try {
|
|
2957
|
-
const result = await sdk.
|
|
2958
|
-
console.log(JSON.stringify({ ...result, next_actions: [{ type: "retry", command: "run402 repos view", why: "the next ordinary
|
|
2956
|
+
const result = await sdk.repos.acceptRecipientKeyChange({ ...target, principal_id: principalId, new_fingerprint: fingerprint });
|
|
2957
|
+
console.log(JSON.stringify({ ...result, next_actions: [{ type: "retry", command: "run402 repos view", why: "the next ordinary vault operation on this machine wraps the vault to the accepted key" }] }, null, 2));
|
|
2959
2958
|
} catch (err) {
|
|
2960
2959
|
reportSdkError(err);
|
|
2961
2960
|
}
|
|
@@ -2968,12 +2967,12 @@ async function accessDeclareExposure(args) {
|
|
|
2968
2967
|
const target = await vaultTarget(a);
|
|
2969
2968
|
try {
|
|
2970
2969
|
const sdk = getSdk();
|
|
2971
|
-
const repoId = target.repo_id ?? (await sdk.
|
|
2972
|
-
const result = await sdk.
|
|
2970
|
+
const repoId = target.repo_id ?? (await sdk.repos.forProject(target.project_id)).repo_id;
|
|
2971
|
+
const result = await sdk.repos.declareEpochSecretExposed(repoId);
|
|
2973
2972
|
printJson(sdk, result);
|
|
2974
2973
|
console.error(`declared epoch_secret_exposed for ${repoId} (epoch_secret_exposure_version now ${result.epoch_secret_exposure_version}).`);
|
|
2975
2974
|
console.error("THIS DECLARATION DOES NOT ROTATE THE VAULT BY ITSELF — the next ordinary push now refuses EPOCH_ROTATION_REQUIRED until a rotate_epoch with reason:\"epoch_secret_exposed\" commits.");
|
|
2976
|
-
console.error("submit that rotation via r.
|
|
2975
|
+
console.error("submit that rotation via r.repos.rotateEpoch({repo_id, reason: \"epoch_secret_exposed\", recipient_state_version, recipient_revocation_version}) once you have the two counter values (no CLI shortcut exists for this reason yet — see `run402 repos access repair --help`).");
|
|
2977
2976
|
console.error("if a /confirm or /repin receipt is already pending for a directory principal, do NOT publish it separately (publishPinManifestUpdate is itself gated the same way) — pass it as rotateEpoch's pending_confirmations instead so it rides the SAME head as this rotation.");
|
|
2978
2977
|
printVerboseStats(a, sdk);
|
|
2979
2978
|
} catch (err) {
|
|
@@ -2981,8 +2980,8 @@ async function accessDeclareExposure(args) {
|
|
|
2981
2980
|
}
|
|
2982
2981
|
}
|
|
2983
2982
|
|
|
2984
|
-
//
|
|
2985
|
-
// existing `access` family: `r.
|
|
2983
|
+
// vault-multi-writer (rev 47) task 6.4 — an on-demand tail on the
|
|
2984
|
+
// existing `access` family: `r.repos.reconcile()` admits every eligible
|
|
2986
2985
|
// `pending_writers[]` candidate right now, rather than waiting for this
|
|
2987
2986
|
// machine's next push/deploy to do it as a side effect. Same shape as
|
|
2988
2987
|
// `accessRepin` above — one SDK call, echo the result, a next_action
|
|
@@ -2998,7 +2997,7 @@ async function accessSync(args) {
|
|
|
2998
2997
|
const sdk = getSdk();
|
|
2999
2998
|
const target = await vaultTarget(a);
|
|
3000
2999
|
try {
|
|
3001
|
-
const result = await sdk.
|
|
3000
|
+
const result = await sdk.repos.reconcile(target);
|
|
3002
3001
|
if (!human) console.log(JSON.stringify(result, null, 2));
|
|
3003
3002
|
if (!result.eligible) {
|
|
3004
3003
|
console.error("this machine's key is not an active writer on this vault — nothing to sync. Ask a current writer to admit you (org membership at role developer+ and a published signing key make you eligible).");
|
|
@@ -3102,7 +3101,7 @@ async function recover(args) {
|
|
|
3102
3101
|
const repoId = flagValue(a, "--repo");
|
|
3103
3102
|
const region = flagValue(a, "--region");
|
|
3104
3103
|
const endpoint = flagValue(a, "--endpoint");
|
|
3105
|
-
//
|
|
3104
|
+
// vault-recovery-custody — the human-member path: --bundle (the exported
|
|
3106
3105
|
// r402s-member-recovery-bundle/v1; omit to use the mirror's own
|
|
3107
3106
|
// member-recovery-bundles/ sidecar) + the source recovery code. --receipt
|
|
3108
3107
|
// supplies the recovery-receipt pin when no keystore holds one (a member
|
|
@@ -3115,7 +3114,7 @@ async function recover(args) {
|
|
|
3115
3114
|
const recoveryReceipt = receiptPath != null ? readJsonFile("--receipt", receiptPath) : undefined;
|
|
3116
3115
|
if (memberBundle !== undefined && code == null) code = await promptSourceRecoveryCode();
|
|
3117
3116
|
try {
|
|
3118
|
-
const result = await sdk.
|
|
3117
|
+
const result = await sdk.repos.recover({
|
|
3119
3118
|
source, out_dir: outDir,
|
|
3120
3119
|
...(repoId != null ? { repo_id: repoId } : {}),
|
|
3121
3120
|
...(credential ? { credential } : {}),
|
|
@@ -3161,7 +3160,7 @@ async function recover(args) {
|
|
|
3161
3160
|
}
|
|
3162
3161
|
}
|
|
3163
3162
|
|
|
3164
|
-
// ─── recovery-bundle (
|
|
3163
|
+
// ─── recovery-bundle (vault-recovery-custody — the export half of `recover`) ─
|
|
3165
3164
|
|
|
3166
3165
|
/**
|
|
3167
3166
|
* `run402 repos recovery-bundle` — export YOUR member recovery bundle
|
|
@@ -3218,7 +3217,7 @@ async function recoveryBundle(args) {
|
|
|
3218
3217
|
|
|
3219
3218
|
/**
|
|
3220
3219
|
* `run402 repos daemon <status|stop>` — the resident helper engine
|
|
3221
|
-
* (
|
|
3220
|
+
* (vault-persistent-helper D4). Purely local: a bounded socket probe,
|
|
3222
3221
|
* never the network. `status` reports `{running:false}` when no daemon
|
|
3223
3222
|
* answers (not an error — the daemon is an accelerator, never a
|
|
3224
3223
|
* dependency); `stop` is idempotent the same way.
|
|
@@ -3293,9 +3292,9 @@ export async function run(sub, args) {
|
|
|
3293
3292
|
console.log(HELP);
|
|
3294
3293
|
process.exit(0);
|
|
3295
3294
|
}
|
|
3296
|
-
//
|
|
3295
|
+
// vault-connection-amortization (bench P5): overlap the API dial with
|
|
3297
3296
|
// the verb's local work — fire-and-forget, silent on every failure.
|
|
3298
|
-
void import("#sdk/node").then((m) => m.
|
|
3297
|
+
void import("#sdk/node").then((m) => m.prewarmVaultConnection()).catch(() => {});
|
|
3299
3298
|
switch (sub) {
|
|
3300
3299
|
case "create": {
|
|
3301
3300
|
await create(argv);
|
|
@@ -3317,8 +3316,8 @@ export async function run(sub, args) {
|
|
|
3317
3316
|
await del(argv);
|
|
3318
3317
|
break;
|
|
3319
3318
|
}
|
|
3320
|
-
case "
|
|
3321
|
-
await
|
|
3319
|
+
case "capture": {
|
|
3320
|
+
await capture(argv);
|
|
3322
3321
|
break;
|
|
3323
3322
|
}
|
|
3324
3323
|
case "handoff": {
|