run402-mcp 4.94.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 +39 -41
- package/core/dist/keystore.d.ts +1 -1
- package/core/dist/keystore.js +1 -1
- package/dist/active-project.js +2 -2
- package/dist/active-project.js.map +1 -1
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/result-store.d.ts +2 -2
- package/dist/result-store.d.ts.map +1 -1
- package/dist/result-store.js +1 -1
- package/dist/tools/deploy-rehearse.js +2 -2
- package/dist/tools/deploy-rehearse.js.map +1 -1
- package/dist/tools/domains.d.ts +2 -2
- package/dist/tools/domains.d.ts.map +1 -1
- package/dist/tools/domains.js +6 -5
- package/dist/tools/domains.js.map +1 -1
- package/dist/tools/get-buzz-route.js +1 -1
- package/dist/tools/get-buzz-route.js.map +1 -1
- package/dist/tools/orgs.d.ts +1 -1
- package/dist/tools/orgs.js +1 -1
- package/dist/tools/project-archives.js +1 -1
- package/dist/tools/project-archives.js.map +1 -1
- package/dist/tools/{gitvault.d.ts → repos.d.ts} +7 -7
- package/dist/tools/repos.d.ts.map +1 -0
- package/dist/tools/{gitvault.js → repos.js} +26 -26
- package/dist/tools/repos.js.map +1 -0
- package/dist/tools/tier-status.js +1 -1
- package/dist/tools/tier-status.js.map +1 -1
- package/dist/tools/transfers.js +6 -6
- package/dist/tools/transfers.js.map +1 -1
- package/package.json +5 -6
- package/schemas/release-spec.v1.json +2 -6
- package/sdk/README.md +44 -44
- package/sdk/core-dist/keystore.d.ts +1 -1
- package/sdk/core-dist/keystore.js +1 -1
- package/sdk/dist/actions.d.ts +3 -3
- package/sdk/dist/actions.d.ts.map +1 -1
- package/sdk/dist/app-up.d.ts +2 -2
- package/sdk/dist/app-up.d.ts.map +1 -1
- package/sdk/dist/config.d.ts +1 -2
- package/sdk/dist/config.d.ts.map +1 -1
- package/sdk/dist/config.js.map +1 -1
- package/sdk/dist/credentials.d.ts +1 -1
- package/sdk/dist/errors.d.ts +6 -6
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js +1 -1
- package/sdk/dist/errors.js.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 +9 -9
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/namespaces/admin.d.ts +1 -1
- package/sdk/dist/namespaces/admin.d.ts.map +1 -1
- package/sdk/dist/namespaces/ai.d.ts +1 -1
- package/sdk/dist/namespaces/ai.js +2 -2
- package/sdk/dist/namespaces/ai.js.map +1 -1
- package/sdk/dist/namespaces/assets.js +1 -1
- package/sdk/dist/namespaces/assets.js.map +1 -1
- package/sdk/dist/namespaces/ci.js +3 -3
- package/sdk/dist/namespaces/ci.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 +45 -46
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +19 -19
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/domains.d.ts +10 -2
- package/sdk/dist/namespaces/domains.d.ts.map +1 -1
- package/sdk/dist/namespaces/domains.js +10 -5
- package/sdk/dist/namespaces/domains.js.map +1 -1
- package/sdk/dist/namespaces/errors.js +1 -1
- package/sdk/dist/namespaces/functions.js +1 -1
- package/sdk/dist/namespaces/functions.js.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} +438 -451
- package/sdk/dist/namespaces/repos.d.ts.map +1 -0
- package/sdk/dist/namespaces/{gitvault.js → repos.js} +454 -462
- 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 +4 -4
- package/sdk/dist/namespaces/tier.d.ts.map +1 -1
- package/sdk/dist/namespaces/transfers.d.ts +46 -15
- package/sdk/dist/namespaces/transfers.d.ts.map +1 -1
- package/sdk/dist/namespaces/transfers.js.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/actions-node.js +8 -8
- package/sdk/dist/node/actions-node.js.map +1 -1
- package/sdk/dist/node/assets-node.js +6 -6
- package/sdk/dist/node/assets-node.js.map +1 -1
- 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/ci.js +1 -1
- package/sdk/dist/node/ci.js.map +1 -1
- package/sdk/dist/node/credentials.d.ts +1 -1
- package/sdk/dist/node/credentials.js +1 -1
- package/sdk/dist/node/deploy-manifest.d.ts +3 -5
- package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
- package/sdk/dist/node/deploy-manifest.js +3 -12
- package/sdk/dist/node/deploy-manifest.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/manifest-export.js +2 -2
- package/sdk/dist/node/manifest-export.js.map +1 -1
- package/sdk/dist/node/org-adopt.js +1 -1
- package/sdk/dist/node/org-adopt.js.map +1 -1
- package/sdk/dist/node/sites-node.js +1 -1
- package/sdk/dist/node/sites-node.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/scoped.d.ts +8 -8
- package/sdk/dist/scoped.d.ts.map +1 -1
- package/sdk/dist/scoped.js +3 -3
- package/sdk/dist/scoped.js.map +1 -1
- package/dist/tools/add-custom-domain.d.ts +0 -18
- package/dist/tools/add-custom-domain.d.ts.map +0 -1
- package/dist/tools/add-custom-domain.js +0 -19
- package/dist/tools/add-custom-domain.js.map +0 -1
- package/dist/tools/check-domain-status.d.ts +0 -16
- package/dist/tools/check-domain-status.d.ts.map +0 -1
- package/dist/tools/check-domain-status.js +0 -12
- package/dist/tools/check-domain-status.js.map +0 -1
- package/dist/tools/gitvault.d.ts.map +0 -1
- package/dist/tools/gitvault.js.map +0 -1
- package/dist/tools/list-custom-domains.d.ts +0 -14
- package/dist/tools/list-custom-domains.d.ts.map +0 -1
- package/dist/tools/list-custom-domains.js +0 -11
- package/dist/tools/list-custom-domains.js.map +0 -1
- package/dist/tools/remove-custom-domain.d.ts +0 -16
- package/dist/tools/remove-custom-domain.d.ts.map +0 -1
- package/dist/tools/remove-custom-domain.js +0 -15
- package/dist/tools/remove-custom-domain.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/README.md
CHANGED
|
@@ -103,7 +103,7 @@ run402 up --manifest run402.deploy.ts --require-plan plan_...
|
|
|
103
103
|
import { defineConfig, dir, nodeFunction, sqlFile } from "@run402/sdk/config";
|
|
104
104
|
|
|
105
105
|
export default defineConfig(({ env }) => ({
|
|
106
|
-
|
|
106
|
+
project_id: env.required("RUN402_PROJECT_ID"),
|
|
107
107
|
database: { migrations: [sqlFile("db/001_init.sql")] },
|
|
108
108
|
site: { replace: dir("dist"), public_paths: { mode: "implicit" } },
|
|
109
109
|
functions: { replace: { api: nodeFunction("dist/functions/api.js") } },
|
|
@@ -215,7 +215,7 @@ Apply-v1 routes and static public paths are release resources: the release point
|
|
|
215
215
|
|
|
216
216
|
Omit `routes` or pass `routes: null` to carry forward base routes. Use `routes: { "replace": [] }` to clear the route table. Route entries are an ordered `replace` list, not a path-keyed map. Function targets use `{ "type": "function", "name": "<materialized function name>" }`. Static route targets use exact patterns only, methods `["GET"]` or `["GET","HEAD"]`, and `{ "pattern": "/events", "methods": ["GET","HEAD"], "target": { "type": "static", "file": "events.html" } }` where `file` is a release static asset path, not a public path, URL, CAS hash, rewrite, or redirect. Use static route targets for method-aware aliases such as static `GET /login` plus function `POST /login`; in explicit public path mode the backing asset can stay private by filename. Direct `/functions/v1/:name` calls remain API-key protected; browser-routed paths are public same-origin ingress.
|
|
217
217
|
|
|
218
|
-
Function routes can charge a fixed tenant x402 price before the handler runs by adding `pricing: { "mode": "always", "amount_usd_micros": 250000, "pay_to": "org_default_payout" }` to the route entry. `250000` is $0.25 per matching action. The portable ReleaseSpec contract also accepts `receipt: "on_fulfillment"` on a priced function route; a compatible host then requires the function to return `payment.fulfilled(response)` before it authors a receipt. Run402-hosted advertising remains gated off until the standard delegated-signer carrier is available—receipt intent never silently downgrades. Omit `networks` for production mainnet only; include `"testnet"` explicitly for testnet acceptance. Static aliases cannot be priced, direct function invocation is not monetized, and service/admin keys do not bypass a priced browser route. The owning org must have a resolvable payout wallet: set it with `run402
|
|
218
|
+
Function routes can charge a fixed tenant x402 price before the handler runs by adding `pricing: { "mode": "always", "amount_usd_micros": 250000, "pay_to": "org_default_payout" }` to the route entry. `250000` is $0.25 per matching action. The portable ReleaseSpec contract also accepts `receipt: "on_fulfillment"` on a priced function route; a compatible host then requires the function to return `payment.fulfilled(response)` before it authors a receipt. Run402-hosted advertising remains gated off until the standard delegated-signer carrier is available—receipt intent never silently downgrades. Omit `networks` for production mainnet only; include `"testnet"` explicitly for testnet acceptance. Static aliases cannot be priced, direct function invocation is not monetized, and service/admin keys do not bypass a priced browser route. The owning org must have a resolvable payout wallet: set it with `run402 orgs payout-wallet <org_id> <wallet_address>`. Conditional credit systems should expose one fixed-price route such as `POST /api/credits`, then keep the rest of the app behind unpriced routes and app-local authorization.
|
|
219
219
|
|
|
220
220
|
Matching is exact or final-prefix-wildcard only. `/admin` and `/admin/` are exact trailing-slash equivalents; `/admin/*` matches children but not `/admin`, `/admin/`, `/admin.css`, or `/administrator`, so deploy both `/admin` and `/admin/*` for a routed section root. Query strings are ignored for matching and preserved in the handler's full public `req.url`. Exact routes beat prefix routes; longest prefix wins; method-compatible dynamic routes beat static assets. A `POST /login` route can coexist with static `GET /login` HTML. Unsafe method mismatch returns `405`, and matched dynamic route failures fail closed instead of falling back to static files.
|
|
221
221
|
|
|
@@ -310,11 +310,11 @@ run402 projects sql prj_example "SELECT count(*) FROM audit"
|
|
|
310
310
|
|
|
311
311
|
### repos: your repository history, encrypted before it leaves the machine
|
|
312
312
|
|
|
313
|
-
`run402 repos` is a Git remote whose contents are encrypted on your own machine and stored as a chain of signed, admitted heads. It exists so your repository history outlives the machine it was written on — without that outliving requiring you to hand Run402 the plaintext. The wire protocol is `r402s/v0`. One noun, seventeen verbs
|
|
313
|
+
`run402 repos` is a Git remote whose contents are encrypted on your own machine and stored as a chain of signed, admitted heads. It exists so your repository history outlives the machine it was written on — without that outliving requiring you to hand Run402 the plaintext. The wire protocol is `r402s/v0`. One noun, seventeen verbs: KyGit is the brand, a vault is the resource, a repo is what you have — `run402 repos` on the command line and `r.repos` in the SDK. Two pairs of the seventeen mint and claim a single-use bearer key: `handoff`/`resume` hand a checked-out working tree — dirty state included — from one agent to ANOTHER, the sender stopping; `invite`/`join` bring a SECOND agent into the SAME work while the first keeps going, sharing a coordination room. See "Handoff / resume" and "Invite / join" below.
|
|
314
314
|
|
|
315
315
|
Three claims, three different strengths. These are the entire approved claims vocabulary for this feature:
|
|
316
316
|
|
|
317
|
-
1. **Run402 cannot decrypt your
|
|
317
|
+
1. **Run402 cannot decrypt your vault or repository history. Deployment artifacts remain a disclosed plaintext custody boundary.** Cryptographic, against Run402 itself: in the vault lane, source payload and repository-history content are ciphertext-only; the substrate retains only enumerated plaintext metadata and holds zero vault keys. The deploy lane is separate and disclosed — the platform custodially holds the plaintext artifacts of every deploy. It can read what you deployed; it cannot read what you did not.
|
|
318
318
|
2. **Activation requires vault admission by default; an explicit, audited override can bypass it.** An operational platform invariant, enforced and auditable — not cryptographic against the platform that enforces it.
|
|
319
319
|
3. **Retention is an operational promise of the platform, not a cryptographic guarantee against it** (the host controls timestamps and bytes).
|
|
320
320
|
|
|
@@ -326,9 +326,9 @@ run402 repos create my-notes # project + vault + origin remote,
|
|
|
326
326
|
git push -u origin main # publishes, encrypted before it leaves the machine
|
|
327
327
|
```
|
|
328
328
|
|
|
329
|
-
`origin` is claimed additively: when the directory has no `origin` yet, the scaffold names ours `origin` — `git push origin main` just works, no side-remote name to remember. An existing `origin` is never touched; the fallback is `run402` instead, and the response says which happened and why. An app that lives inside another repository (a monorepo workspace) is never scaffolded into that repository: the skip carries a `create_nested_repo` next action, and `run402 repos create --nested --project <
|
|
329
|
+
`origin` is claimed additively: when the directory has no `origin` yet, the scaffold names ours `origin` — `git push origin main` just works, no side-remote name to remember. An existing `origin` is never touched; the fallback is `run402` instead, and the response says which happened and why. An app that lives inside another repository (a monorepo workspace) is never scaffolded into that repository: the skip carries a `create_nested_repo` next action, and `run402 repos create --nested --project <project_id>` (or `run402 up --nested`) gives the app root its own nested repository and `run402` remote, appending exactly one line to the enclosing repository's local `.git/info/exclude` and touching nothing else there; `repos create` prints a `git push` next action only for a remote it actually added. The free path is the whole path — no slug, no fee, no ceremony. When you want pretty `run402::<org-slug>/<name>` addresses (clone-by-name, push-to-create), claim an org slug once — the optional named-address upgrade described below.
|
|
330
330
|
|
|
331
|
-
**Named addressing.** `run402::<org-slug>/<name>` works alongside the id-form `run402::<org_id>/<project_id>` in the same slot — pick an org slug once (`run402
|
|
331
|
+
**Named addressing.** `run402::<org-slug>/<name>` works alongside the id-form `run402::<org_id>/<project_id>` in the same slot — pick an org slug once (`run402 orgs slug <slug>`, owner-only, a small one-time fee), and every repo under it is `run402::<slug>/<name>`. Pushing a name that doesn't exist yet **push-to-creates** it: the project and vault are allocated atomically, and a losing concurrent pusher resolves cleanly to the winner's repo instead of erroring — its work is not lost, it just wasn't the creator. The first time a named remote resolves on a checkout, the resolved id is **pinned** into that checkout's local git config — every later push/fetch follows the pin directly, so a later rename of the org slug or repo name never breaks an existing clone. The id-form address needs no pin (a project id never changes) and stays the cold-restart path: an agent that lost its local state but still holds authority on the project can always fall back to `run402::<org_id>/<project_id>`.
|
|
332
332
|
|
|
333
333
|
**One thing to know up front: a vault has a writer set, not a single key.** Every admitted member or handoff recipient opens the vault and pushes under its OWN keystore key (`run402 repos access` lists them). A vault whose only admitted principal is this keystore is exactly as safe as this keystore — see "If you lose the keystore" below, or admit a second principal.
|
|
334
334
|
|
|
@@ -344,14 +344,14 @@ run402 init
|
|
|
344
344
|
# 2. Allocate the repo's vault explicitly. Separate from `run402 init` on
|
|
345
345
|
# purpose: this is the step that mints key material on this machine and
|
|
346
346
|
# prints a one-shot recovery receipt. Idempotent — an existing vault comes
|
|
347
|
-
# back deduplicated. (Skip this step and git push / repos
|
|
347
|
+
# back deduplicated. (Skip this step and git push / repos capture
|
|
348
348
|
# against an unallocated project allocates the SAME way, lazily, on
|
|
349
349
|
# first use — the two paths don't stack; this one just does it now,
|
|
350
350
|
# explicitly, so the receipt lands in JSON stdout instead of stderr.)
|
|
351
|
-
run402 repos create --project <
|
|
351
|
+
run402 repos create --project <project_id>
|
|
352
352
|
|
|
353
353
|
# 3. Snapshot — capture the working tree, encrypt it, publish a signed head.
|
|
354
|
-
run402 repos
|
|
354
|
+
run402 repos capture --message "wip: refactor the parser"
|
|
355
355
|
git push origin main # ...or push your own branches, via git-remote-run402
|
|
356
356
|
|
|
357
357
|
# 4. View, then fsck: walk the head chain from your authenticated pin.
|
|
@@ -366,25 +366,25 @@ Cloning needs a Run402 principal on this machine — a wallet and a keystore hol
|
|
|
366
366
|
|
|
367
367
|
A fresh clone installs local `refs/r402/retain/<oid>` refs for every retained deploy-capture tip no branch reaches, so a plain `git fsck` is silent — `git for-each-ref refs/r402/` lists what is retained. Clones made by a client older than this one (or a checkout whose ref write degraded) may still show dangling commits under `git fsck`; harmless, not corruption — one `run402 repos fsck` run installs the missing refs. A retained ref locally pins that history against `git gc` until the vault prunes the capture, at which point the next fetch retracts it.
|
|
368
368
|
|
|
369
|
-
`repos
|
|
369
|
+
`repos capture` is the CAPTURE lane — the protocol deploy ref plus the HEAD target — because a dirty tree captures as a synthetic commit that sits on no branch. Your own branches and tags reach the vault through `git push origin <branch>`.
|
|
370
370
|
|
|
371
|
-
**Allocating a vault does NOT gate the project's deploys.** `
|
|
371
|
+
**Allocating a vault does NOT gate the project's deploys.** `vault_policy` stays unset until you set it — a vault created by a first `git push` or `repos create` never silently changes how you deploy. A deploy against a vaulted, ungated project proceeds ungated and its result carries a typed `next_actions` entry offering `run402 repos policy required`; every later ungated deploy carries a `warnings[]` entry naming the drift, until the policy is set either way — never a block, never an interactive prompt. Once `vault_policy` is `required`, a deploy must present a vaulted capture at commit — `run402 deploy` produces one automatically on any machine holding the keystore; un-gate with `run402 repos policy grandfathered --reason "<why>"` (owner + step-up, audited, reversible with `run402 repos policy required`). Vaulting your source is never gated on a deploy, either way. `run402 doctor` reports the policy, whether this machine can satisfy it, and where the keystore lives.
|
|
372
372
|
|
|
373
|
-
Before `
|
|
373
|
+
Before `capture` reports that anything landed, the client compares every finalization receipt against its local expected manifest and reads the admitted head back from storage — a 200 alone is never enough. Maintenance is one verb, `run402 repos gc` — `git gc`'s own two halves (checkpoint publication + prune planning), never described as "exactly `git gc`" since the deletion ceremony is stricter: it plans locally, and submits only when handed both verifier receipts — one from this CLI, one from the independent `r402s-verify` — with `--submit --intent-core <path> --verifier-receipt <path>`; only the control-plane-signed completion says what was deleted.
|
|
374
374
|
|
|
375
375
|
From the SDK, with identical semantics — vault reads run anywhere, and the verbs that touch a git working tree or the on-disk keystore are Node-only:
|
|
376
376
|
|
|
377
377
|
For typed repository automation, see the [native SDK KyGit reference](https://docs.run402.com/sdk/resources/).
|
|
378
378
|
|
|
379
|
-
**The encrypted second remote — the zero-migration pattern.** Keep GitHub/GitLab as the primary (collaboration, CI, reviews, unchanged) and add KyGit as the second remote: `git remote add
|
|
379
|
+
**The encrypted second remote — the zero-migration pattern.** Keep GitHub/GitLab as the primary (collaboration, CI, reviews, unchanged) and add KyGit as the second remote: `git remote add vault run402::<org_id>/<project_id>` + `git push vault --all`, and a complete, continuously updated copy of your history exists that the storage provider itself cannot read. The reason this matters, said plainly and as capability rather than accusation: a host that can READ private repositories can — under a future policy, an acquisition, a training pipeline, a subpoena, or a breach — index them, train models on them, or hand them to someone who will. Run402 cannot decrypt your vault or repository history. Deployment artifacts remain a disclosed plaintext custody boundary.
|
|
380
380
|
|
|
381
381
|
**A vault-only project is first-class.** `run402 init` (or `run402 repos create <name>`), then `git push origin …`, then `gc` / `fsck` / `access`, and never a deploy — a supported shape, not a degraded one. One consequence is worth stating plainly: a vault-only project has no deploy lane, so the disclosed plaintext custody boundary is empty and there is consequently no custodial restore path.
|
|
382
382
|
|
|
383
|
-
**If you lose the keystore.** The vault protects source history from host-side loss while a principal keystore survives. The "while" clause is load-bearing: in V0-A, **whole-machine or whole-keystore loss is terminal for vault history until human envelopes ship**, and `run402 repos view` prints that sentence verbatim. Back up the keystore directory `run402 repos view` reports as `keystore.root` and prints under the terminal-loss statement — `~/.config/run402/
|
|
383
|
+
**If you lose the keystore.** The vault protects source history from host-side loss while a principal keystore survives. The "while" clause is load-bearing: in V0-A, **whole-machine or whole-keystore loss is terminal for vault history until human envelopes ship**, and `run402 repos view` prints that sentence verbatim. Back up the keystore directory `run402 repos view` reports as `keystore.root` and prints under the terminal-loss statement — `~/.config/run402/vault` for the default wallet, `~/.config/run402/profiles/<wallet>/vault` for a named one. The recovery receipt is an integrity anchor, not a decryption key — it proves the vault you are served is the one you created, and it decrypts nothing. It is not a secret; the more copies the better. The reminder gets louder as the vault gets more valuable: quiet at genesis, a STANDING `run402 doctor` warning once the vault crosses any of ≥10 generations / ≥10 MB / ≥14 days since genesis — cleared only by adding a second principal, never by an attestation, because V0 cannot verify one is true.
|
|
384
384
|
|
|
385
|
-
**The exit ramp: mirror your own copy.** `run402 repos mirror <destination> [--profile <name> | --ambient]` (S3 or a plain directory) configures a second, customer-owned copy of the vault's ciphertext — the destination and credential *name* live in a config file beside the keystore, never in `run402.config.json`, never a raw secret. Once set, every
|
|
385
|
+
**The exit ramp: mirror your own copy.** `run402 repos mirror <destination> [--profile <name> | --ambient]` (S3 or a plain directory) configures a second, customer-owned copy of the vault's ciphertext — the destination and credential *name* live in a config file beside the keystore, never in `run402.config.json`, never a raw secret. Once set, every capture is mirrored to it automatically, reported as a separate `mirror_push` field beside the vault result; a mirror failure never blocks, slows, or changes the actual publish. `run402 repos mirror --backfill` (idempotent, resumable) catches it up on demand; `run402 repos fsck --mirror` is a KEYLESS integrity probe — it reports the recoverable generation without touching key material. `run402 repos recover <source> --out <dir>` needs no server at all: it reads the mirror, verifies the chain, and decrypts with the local keystore alone. Named `recover` rather than `restore`, which already means something else in git. Two things to know before you rely on it: it proves *validity, never freshness* — an older mirror looks identical to a genuinely short history — and a mirror without the keystore **or an equivalent key** recovers nothing, since mirroring ciphertext does not create a second key; the V0 terminal-loss statement above applies.
|
|
386
386
|
|
|
387
|
-
**The human backup path (
|
|
387
|
+
**The human backup path (vault-recovery-custody).** A human org member who completed source enrollment at console.run402.com/account holds an *equivalent key* with no keystore at all: their member key lives as sealed wrappers (passkey PRF and/or a source recovery code), and `run402 repos recovery-bundle` downloads the versioned recovery bundle (key identity + wrapper ciphertexts — still nothing the platform can open). Kept with a vault mirror — copy it to `member-recovery-bundles/<name>.json` under the mirrored prefix — that bundle + the source recovery code + the vault's recovery receipt recover the repository with **no run402 server and no keystore**: `run402 repos recover <source> --out <dir> --receipt <pin.json>` (the code is prompted with hidden input; `--bundle <file>` if the bundle isn't in the mirror). A raw passkey PRF output is deliberately NOT a recovery input — the no-server path for a human is the recovery code. `run402 doctor`'s `recovery_posture` check tells you whether each vault-owning org actually has this backstop configured.
|
|
388
388
|
|
|
389
389
|
```bash
|
|
390
390
|
run402 repos mirror s3://acme-vault-mirror --profile acme --region us-east-1
|
|
@@ -403,9 +403,9 @@ run402 repos resume kgh1_… # on the other machine: red
|
|
|
403
403
|
|
|
404
404
|
Neither verb has an MCP tool — `handoff` mints a bearer secret and `resume` mutates org membership, the same "mutating verbs are CLI-only" reasoning as `create`/`delete` above.
|
|
405
405
|
|
|
406
|
-
**Writers, plural.** A vault admits heads from a SET of writer keys, each a member's own keystore identity (protocol rev 47). `resume` makes the recipient a writer before it returns — `git push` works at once, under the recipient's own key, and the sender's environment can be deleted afterwards. Any member added with `run402
|
|
406
|
+
**Writers, plural.** A vault admits heads from a SET of writer keys, each a member's own keystore identity (protocol rev 47). `resume` makes the recipient a writer before it returns — `git push` works at once, under the recipient's own key, and the sender's environment can be deleted afterwards. Any member added with `run402 orgs members add` (developer or above) becomes a writer the same way: the adder's client admits the new key inline when it can, and REFUSES the add (`VAULT_WRITER_NOT_ADMITTED`, `request_writer_sync`) when it cannot, so no member is ever left able to read but not push. `run402 repos view` lists `writers[]` and `pending_writers[]`; `run402 repos access sync` admits pending keys on demand; removing a member rides the next epoch rotation and that key can never be re-added. Nobody's seed is ever copied: a writer is admitted by a live writer's signature or by a sender-signed handoff grant the recipient completes with its own key.
|
|
407
407
|
|
|
408
|
-
**Invite / join — bring a second agent into the exact work, dirty tree included, and talk in a shared room.** A Handoff passes the work on; an Invite grows the team. `run402 repos invite` captures the working tree exactly like `handoff` does — the inviter's own worktree, index, branch, refs, and access are all untouched, and it keeps pushing throughout — registers the inviter's own presence in a coordination room (the project's default room, or `--room <key>` for a named org room), mints a single-use bearer key, `kgi1_…`, printed to stdout exactly once, and posts ONE room message naming the checkpoint and the invite id (never the key). Minting requires an ACTIVE writer key, the same as `handoff` (`INVITE_MINT_REQUIRES_WRITER` names `run402 repos access sync` as the fix). Hand that key to another agent and `run402 repos join kgi1_…` pays its own way in — the joining agent folds the SAME cold-start chain `resume` does (wallet → faucet → one x402 prototype payment) before the redemption, so it arrives as a paid-up run402 wallet of its own — clones a fresh checkout, **becomes a writer of the vault under its OWN key before the command returns** (nothing is copied from the inviter), restores the exact dirty state, pins the invite's room locally, registers its own presence, posts ONE arrival message, and reports who invited it (name, labels, whether they're still live), who else is in the room, and the last few messages. Both agents push, interleaved, each signing under its own key. From there `run402 messages wait` is the agent's ear: it blocks until the other side speaks (or a bounded timeout elapses) using the gateway's held read, never errors on silence, and reports who is still live either way. The minted role defaults to `developer` and never exceeds the inviter's own; the Invite Note (same shape as the Handoff Note) rides alongside and renders as Markdown by default on `join`. Taking access back is `run402
|
|
408
|
+
**Invite / join — bring a second agent into the exact work, dirty tree included, and talk in a shared room.** A Handoff passes the work on; an Invite grows the team. `run402 repos invite` captures the working tree exactly like `handoff` does — the inviter's own worktree, index, branch, refs, and access are all untouched, and it keeps pushing throughout — registers the inviter's own presence in a coordination room (the project's default room, or `--room <key>` for a named org room), mints a single-use bearer key, `kgi1_…`, printed to stdout exactly once, and posts ONE room message naming the checkpoint and the invite id (never the key). Minting requires an ACTIVE writer key, the same as `handoff` (`INVITE_MINT_REQUIRES_WRITER` names `run402 repos access sync` as the fix). Hand that key to another agent and `run402 repos join kgi1_…` pays its own way in — the joining agent folds the SAME cold-start chain `resume` does (wallet → faucet → one x402 prototype payment) before the redemption, so it arrives as a paid-up run402 wallet of its own — clones a fresh checkout, **becomes a writer of the vault under its OWN key before the command returns** (nothing is copied from the inviter), restores the exact dirty state, pins the invite's room locally, registers its own presence, posts ONE arrival message, and reports who invited it (name, labels, whether they're still live), who else is in the room, and the last few messages. Both agents push, interleaved, each signing under its own key. From there `run402 messages wait` is the agent's ear: it blocks until the other side speaks (or a bounded timeout elapses) using the gateway's held read, never errors on silence, and reports who is still live either way. The minted role defaults to `developer` and never exceeds the inviter's own; the Invite Note (same shape as the Handoff Note) rides alongside and renders as Markdown by default on `join`. Taking access back is `run402 orgs members rm`, which rotates the vault's epoch so the removed key can no longer push while every remaining agent keeps working.
|
|
409
409
|
|
|
410
410
|
```bash
|
|
411
411
|
run402 repos invite --note-file invite.json # captures the working tree, mints the key, prints it ALONE to stdout
|
|
@@ -415,7 +415,7 @@ run402 messages wait # then: block until the other
|
|
|
415
415
|
|
|
416
416
|
Like `handoff`/`resume`, neither `invite` nor `join` has an MCP tool — `invite` mints a bearer secret and `join` mutates org membership and writes a working tree, the same reasoning as `create`/`delete`/`handoff`/`resume` above.
|
|
417
417
|
|
|
418
|
-
**Verify it without trusting our client.** `r402s-verify` is an independent-lineage verifier for the same protocol — a separate language, separate authorship, and a separate primitive stack, deliberately sharing no implementation code with the SDK. That non-sharing is the point: a differential verifier that reuses the code it is checking verifies nothing. It lives on the `r402s-verify` branch of this repository with its own workflow, ships prebuilt release binaries, and also builds with `cargo build --release`. The full protocol specification and threat model it verifies against are published in [`docs/
|
|
418
|
+
**Verify it without trusting our client.** `r402s-verify` is an independent-lineage verifier for the same protocol — a separate language, separate authorship, and a separate primitive stack, deliberately sharing no implementation code with the SDK. That non-sharing is the point: a differential verifier that reuses the code it is checking verifies nothing. It lives on the `r402s-verify` branch of this repository with its own workflow, ships prebuilt release binaries, and also builds with `cargo build --release`. The full protocol specification and threat model it verifies against are published in [`docs/kygit/`](docs/kygit/README.md), and the frozen conformance vectors in [`test-vectors/r402s-v0/`](test-vectors/r402s-v0/README.md).
|
|
419
419
|
|
|
420
420
|
**Cost.** There is no separate repos price — a vault's bytes count against the organization-pooled vault quota (`sourceBytes`: prototype 1 GB, hobby 10 GB, team 50 GB), a separate pool from the storage your projects share, charged once per unique object with a 4 KiB per-object accounting floor and a 1 MiB per-vault minimum.
|
|
421
421
|
|
|
@@ -502,19 +502,19 @@ run402 init # one-shot wallet + faucet + tier check
|
|
|
502
502
|
run402 pay https://seller.example/resource --max-usd 0.05 --require-receipt
|
|
503
503
|
run402 status # organization snapshot (wallet, rail, balances, tier, projects)
|
|
504
504
|
run402 projects provision --name my-app
|
|
505
|
-
run402 projects sql <
|
|
506
|
-
run402 projects validate-expose <
|
|
507
|
-
run402 projects apply-expose <
|
|
505
|
+
run402 projects sql <project_id> "CREATE TABLE …"
|
|
506
|
+
run402 projects validate-expose <project_id> --file manifest.json
|
|
507
|
+
run402 projects apply-expose <project_id> --file manifest.json
|
|
508
508
|
run402 sites deploy-dir ./dist
|
|
509
|
-
run402 deploy verify op_... --project <
|
|
510
|
-
run402 deploy releases active --project <
|
|
511
|
-
run402 deploy resolve https://example.com/events --project <
|
|
509
|
+
run402 deploy verify op_... --project <project_id> --wait # confirm gateway/edge release coherence
|
|
510
|
+
run402 deploy releases active --project <project_id> # inspect current-live release inventory
|
|
511
|
+
run402 deploy resolve https://example.com/events --project <project_id> --method GET
|
|
512
512
|
run402 deploy --manifest app.json --json # deploy only; rehearses automatically when a live release has migrations to protect
|
|
513
513
|
run402 snapshots list prj_...
|
|
514
514
|
run402 branches create prj_... --ttl-days 7 --json
|
|
515
|
-
run402 functions deploy <
|
|
516
|
-
run402 functions runs create <
|
|
517
|
-
run402 ci link github --project <
|
|
515
|
+
run402 functions deploy <project_id> <name> --file fn.ts
|
|
516
|
+
run402 functions runs create <project_id> <name> --event-type reminder.send --idempotency-key reminder:123 --delay 10m
|
|
517
|
+
run402 ci link github --project <project_id> # GitHub Actions OIDC deploy binding (--route-scope for CI routes)
|
|
518
518
|
run402 assets put ./asset.png --immutable
|
|
519
519
|
run402 assets diagnose <url> # inspect live CDN state for a public URL
|
|
520
520
|
run402 cdn wait-fresh <url> --sha <hex> # poll until a mutable URL serves the new SHA
|
|
@@ -524,21 +524,19 @@ run402 cdn wait-fresh <url> --sha <hex> # poll until a mutable URL serves the n
|
|
|
524
524
|
|
|
525
525
|
Rehearsal is automatic: a migration-bearing `run402 up` / `run402 deploy` against a project with a live release is rehearsed on a contained branch and committed only on a passing report (`result.deploy.rehearsal`); a first deploy has nothing to protect and commits directly (`reason: "no_live_release"`), and a redeploy whose migrations are all already applied with identical checksums is skipped as `migrations_unchanged`, so a page-only redeploy that still carries its migrations ships in seconds. `--no-rehearse` skips it. ADVANCED: `run402 deploy rehearse [<plan_id>] [--manifest <path>]` rehearses without committing — from a persisted plan, or from the manifest in the current directory (plan, upload, rehearse). Manual restore points live under `run402 snapshots create|list|get|restore|delete`; restore is a two-step plan/confirm flow. Branch projects live under `run402 branches create|list|renew|delete`, default to a 7-day TTL, use sandboxed email by default, and are marked noindex; a parent with no live release yields an empty branch.
|
|
526
526
|
|
|
527
|
-
Your HTML never needs a pasted key: every Run402 host serves `/_run402/config.js` (`window.RUN402 = { project_id, api_base, anon_key }`) for the project it resolves to. `run402 up` also names this principal when it has none — `RUN402_AGENT_NAME` if your runtime declares one (it overrides an existing name), else a detected client (`claude-code`, `codex`, `cursor`, `grok`; `RUN402_CLIENT=<name>` declares a client with no marker of its own, checked first); when nothing is known nothing is written — so promotion credit names you; set it any time with `run402
|
|
527
|
+
Your HTML never needs a pasted key: every Run402 host serves `/_run402/config.js` (`window.RUN402 = { project_id, api_base, anon_key }`) for the project it resolves to. `run402 up` also names this principal when it has none — `RUN402_AGENT_NAME` if your runtime declares one (it overrides an existing name), else a detected client (`claude-code`, `codex`, `cursor`, `grok`; `RUN402_CLIENT=<name>` declares a client with no marker of its own, checked first); when nothing is known nothing is written — so promotion credit names you; set it any time with `run402 whoami --set-name <name>`. `result.identity` always reports `detected` (the client seen this run) and `detection: { applied, reason }`, where `name_already_set` means a client was detected but the principal already had a name. `projects provision` never touches git; `up` scaffolds a `run402` remote on the app root only, and an app root inside another repository is skipped with a `create_nested_repo` next action unless you pass `--nested`, which makes it its own nested repository (one line appended to the enclosing repository's local `.git/info/exclude`, nothing else touched).
|
|
528
528
|
|
|
529
529
|
Portable archives export the supported run402 Core runtime slice of a Cloud project for local Core import. This is the no-lock-in trust path, separate from allowance/spend-cap financial-risk controls.
|
|
530
530
|
|
|
531
531
|
```bash
|
|
532
|
-
run402
|
|
532
|
+
run402 archives create <project_id> --target cloud --scope portable-runtime-v1 --auth stubs --consistency pause-writes --wait --output ./project.r402ar --json
|
|
533
533
|
run402 archives verify ./project.r402ar --json
|
|
534
|
-
run402
|
|
535
|
-
run402 projects export <project_id> --output ./project.r402ar --json
|
|
536
|
-
run402 core projects apply ./project.r402ar --name imported-project --env-file ./required.env --json
|
|
534
|
+
run402 archives import ./project.r402ar --target core --name imported-project --env-file ./required.env --json
|
|
537
535
|
```
|
|
538
536
|
|
|
539
|
-
`
|
|
537
|
+
`--target` names the deployment each verb talks to: `create`, `status`, and `download` export from Run402 Cloud (`--target cloud`, the default); `import` loads into a local Run402 Core (`--target core`, the default). Archive v1 excludes secret values, auth credentials, logs, billing/allowance state, Cloud operations metadata, Cloud import, and existing-project merge import. Verify is local/offline and checks integrity plus compatibility; archives remain untrusted input until Core import verifies and stages them.
|
|
540
538
|
|
|
541
|
-
The active project is sticky: `run402 projects use <
|
|
539
|
+
The active project is sticky: `run402 projects use <project_id>` server-validates `<project_id>` and stores it as the default for subsequent `<project_id>`-taking subcommands, so most commands work without it. Local key material is managed separately under `run402 credentials project-keys ...`; that cache is never project inventory.
|
|
542
540
|
|
|
543
541
|
## MCP server: `run402-mcp`
|
|
544
542
|
|
|
@@ -659,7 +657,7 @@ The full MCP surface: every tool is a thin shim over an SDK call.
|
|
|
659
657
|
| `deploy_site_dir` | Deploy a static site from a local directory. Routes through the unified apply primitive (CAS-backed); only uploads bytes the gateway doesn't have. |
|
|
660
658
|
| `add_subdomain` | Claim `<name>.run402.com` (idempotent; binds the live release unless `release_id` / `deployment_id` is given; reassigns to latest deploy on subsequent deploys). |
|
|
661
659
|
| `list_subdomains` / `delete_subdomain` | Manage subdomains. |
|
|
662
|
-
| `
|
|
660
|
+
| `domains_connect` / `domains_get` / `domains_list` / `domains_check` | Manage project-scoped web/email ProjectDomain desired state and health checks. |
|
|
663
661
|
| `domains_apply` / `domains_repair` / `domains_test_receive` / `domains_activate` / `domains_disconnect` | Apply safe provider actions, repair run402-owned routing, verify inbound receive, activate mailbox addresses, or disconnect a domain. |
|
|
664
662
|
| `deploy` / `deploy_resume` / `deploy_rehearse` / `deploy_list` / `deploy_events` / `deploy_verify_edge` | Apply (rehearsal is automatic when a live release has migrations to protect), resume, ADVANCED-rehearse a persisted plan on a contained branch, list, inspect deploy operations, and verify gateway/edge coherence. |
|
|
665
663
|
| `deploy_releases_get` / `deploy_releases_active` / `deploy_releases_diff` | Inspect release inventory and release-to-release diffs without starting a new deploy mutation. |
|
|
@@ -712,7 +710,7 @@ The full MCP surface: every tool is a thin shim over an SDK call.
|
|
|
712
710
|
| `send_email` | Template (`project_invite`, `magic_link`, `notification`) or raw HTML. Single recipient. Omitting `mailbox` uses the configured outbound default; result echoes `mailbox_id` and `from_address` when returned. |
|
|
713
711
|
| `list_emails` / `get_email` / `get_email_raw` | Read messages. `get_email_raw` returns RFC-822 bytes for DKIM / zk-email verification. |
|
|
714
712
|
| `register_mailbox_webhook` / `list_mailbox_webhooks` / `get_mailbox_webhook` / `update_mailbox_webhook` / `delete_mailbox_webhook` | Email-event webhooks (delivery, bounced, complained, reply_received). |
|
|
715
|
-
| `
|
|
713
|
+
| `domains_connect` / `domains_check` / `domains_repair` / `domains_test_receive` | Use ProjectDomain for custom email sending and inbound receive. |
|
|
716
714
|
|
|
717
715
|
### AI helpers
|
|
718
716
|
|
|
@@ -828,11 +826,11 @@ Contact management (who gets paged) is CLI/SDK only by design — an agent raise
|
|
|
828
826
|
| `get_buzz_route` | One route's honest `health` (derived from route + credential state, never queue emptiness) with per-status delivery counts and the `revision` an update must echo — or the org's route list when the route id is omitted. A `pending_authorization` route prints the non-secret step (a Buzz community owner adds the `notification_pubkey` as a relay member) and the exact verify command. |
|
|
829
827
|
| `list_buzz_route_deliveries` | Did it actually land? Keyset newest-first delivery history — dead letters included, the signed envelope never. `queued`/`retryable` are in flight (the publisher tick runs ~every 60s; retries back off to 8 attempts / 48h, then `dead_letter`); `nostr_event_id` appears on delivered rows. |
|
|
830
828
|
|
|
831
|
-
Route mutations (configure / test / pause / resume / rotate / revoke) are CLI/SDK only by design — they need owner step-up, and configure/rotate hand off a Buzz-side authorization a human completes: `run402 buzz notifications configure --org <uuid> --installation <buzzci_id> --name <route_name> --channel <nip29-channel-id> --project <
|
|
829
|
+
Route mutations (configure / test / pause / resume / rotate / revoke) are CLI/SDK only by design — they need owner step-up, and configure/rotate hand off a Buzz-side authorization a human completes: `run402 buzz notifications configure --org <uuid> --installation <buzzci_id> --name <route_name> --channel <nip29-channel-id> --project <project_id>`. No surface anywhere accepts or prints a signing secret. Buzz is never a deadman channel: mandatory owner notifications keep their human paths regardless of route state.
|
|
832
830
|
|
|
833
831
|
### repos (read-only) — the host-blind encrypted git repo family
|
|
834
832
|
|
|
835
|
-
One noun across every agent surface: `repos_view` / `repos_list_heads` / `repos_fsck` teach only `repos` CLI spellings. `
|
|
833
|
+
One noun across every agent surface: `repos_view` / `repos_list_heads` / `repos_fsck` teach only `repos` CLI spellings. `r.repos` is the SDK's name.
|
|
836
834
|
|
|
837
835
|
| Tool | Description |
|
|
838
836
|
|------|-------------|
|
|
@@ -840,7 +838,7 @@ One noun across every agent surface: `repos_view` / `repos_list_heads` / `repos_
|
|
|
840
838
|
| `repos_list_heads` | One page of a repo's heads listing — the admitted generations above a fixed anchor, each with its stored-bytes hash. `after_generation` is the VERIFICATION ANCHOR, not a paging knob, and must stay identical across every page of one sequence; `cursor` is opaque (store and echo, never parse). Listing is not verifying. |
|
|
841
839
|
| `repos_fsck` | Verify the head chain from your authenticated pin up to the newest listed generation, then advance the pin to what was proved. Monotonic and non-destructive. Fails CLOSED, and the refusal is the answer: `GENERATION_REGRESSION` on a rollback, `CHAIN_BROKEN` on a gap, `UPGRADE_REQUIRED` on a transition this client cannot validate, `VERIFICATION_BUDGET_EXCEEDED` when the per-call budget runs out (a pause, not a failure — the verified prefix persists). The CLI's `run402 repos fsck` also materializes the ref map and supports `--no-write`/`--mirror`; this tool is the chain-walk half only. |
|
|
842
840
|
|
|
843
|
-
The repo's mutating verbs are deliberately CLI-only. `
|
|
841
|
+
The repo's mutating verbs are deliberately CLI-only. `capture` / `create` write an IMMUTABLE generation with no undo, and `create` mints the one-shot recovery receipt — an MCP transcript is the wrong place for the only copy of it to exist. `gc` holds a maintenance lease whose `holder_token` is returned exactly once, so a dropped session strands it, and its submit half is destructive by contract. `policy` needs owner membership plus step-up, which the MCP credential path does not carry. `handoff` and `invite` each mint a single-use bearer secret, and `resume` and `join` each mutate org membership — the same reasoning, one MCP transcript is the wrong place for a secret that must be printed exactly once. All seventeen verbs are reachable as `run402 repos …` (`repo` singular resolves identically).
|
|
844
842
|
|
|
845
843
|
### Service status (no auth)
|
|
846
844
|
|
|
@@ -865,7 +863,7 @@ Local state lives at:
|
|
|
865
863
|
- profile `credentials/project-keys.v1.json` (`0600`): local anon/service key cache for explicit credential-required operations
|
|
866
864
|
- `~/.config/run402/wallet.json` (`0600`): wallet for x402 / MPP signing
|
|
867
865
|
|
|
868
|
-
Legacy `projects.json` files are one-way migration input only. `anon_key` and `service_key` have no expiry; lease enforcement happens server-side. Inspect cache state with `run402 credentials project-keys status --project <
|
|
866
|
+
Legacy `projects.json` files are one-way migration input only. `anon_key` and `service_key` have no expiry; lease enforcement happens server-side. Inspect cache state with `run402 credentials project-keys status --project <project_id>` and export secrets only with `run402 credentials project-keys export --project <project_id> --reveal`.
|
|
869
867
|
|
|
870
868
|
## Development
|
|
871
869
|
|
package/core/dist/keystore.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface StoredProject {
|
|
|
6
6
|
last_deployment_id?: string;
|
|
7
7
|
/**
|
|
8
8
|
* The owning organization, cached so a returning machine can build addresses
|
|
9
|
-
* that need it — the `run402::<org_id>/<project_id>`
|
|
9
|
+
* that need it — the `run402::<org_id>/<project_id>` vault remote is the
|
|
10
10
|
* first — WITHOUT a control-plane round trip.
|
|
11
11
|
*
|
|
12
12
|
* NOT a secret and NOT an authorization input: it is a routing identifier the
|
package/core/dist/keystore.js
CHANGED
|
@@ -190,7 +190,7 @@ export function removeProject(projectId, path) {
|
|
|
190
190
|
* bucket, not "unknown") and PERMANENTLY shadows every later wallet-scoped
|
|
191
191
|
* activation for every caller that reads through this module: `resolveProjectId`
|
|
192
192
|
* / `resolveProject` (cli/lib/config.mjs), `projects current`, and every
|
|
193
|
-
*
|
|
193
|
+
* vault-verb target resolution. The failure it causes: `repos create`
|
|
194
194
|
* calls `projects.provision`, whose `creds.setActiveProject` correctly
|
|
195
195
|
* persists the new project under the real wallet's scoped bucket AND the
|
|
196
196
|
* flat fallback, yet every CLI read of "the active project" resolves the
|
package/dist/active-project.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* MCP DB tools (`run_sql`, `get_schema`, `rest_query`) accept an optional
|
|
5
5
|
* `project_id`. When omitted, we fall back to the active project tracked in
|
|
6
|
-
* local state (set by provisioning or `run402 projects use <
|
|
6
|
+
* local state (set by provisioning or `run402 projects use <project_id>`), so an agent
|
|
7
7
|
* working against a single project doesn't have to thread the id through every
|
|
8
8
|
* call. Returns the resolved id, or an error ToolResult when neither an explicit
|
|
9
9
|
* id nor an active project is available.
|
|
@@ -28,7 +28,7 @@ export async function resolveProjectId(projectId) {
|
|
|
28
28
|
{
|
|
29
29
|
type: "text",
|
|
30
30
|
text: "No project_id provided and no active project is set. Pass project_id explicitly, " +
|
|
31
|
-
"or set an active project first (provision one, or `run402 projects use <
|
|
31
|
+
"or set an active project first (provision one, or `run402 projects use <project_id>`).",
|
|
32
32
|
},
|
|
33
33
|
],
|
|
34
34
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"active-project.js","sourceRoot":"","sources":["../src/active-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAkB;IAElB,MAAM,QAAQ,GAAG,SAAS,EAAE,IAAI,EAAE,CAAC;IACnC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EACF,mFAAmF;oBACnF,
|
|
1
|
+
{"version":3,"file":"active-project.js","sourceRoot":"","sources":["../src/active-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAkB;IAElB,MAAM,QAAQ,GAAG,SAAS,EAAE,IAAI,EAAE,CAAC;IACnC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EACF,mFAAmF;oBACnF,wFAAwF;aAC3F;SACF;KACF,CAAC;AACJ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -113,7 +113,7 @@ import { scaffoldRolesSchema, handleScaffoldRoles } from "./tools/scaffold-roles
|
|
|
113
113
|
import { createAuthUserSchema, handleCreateAuthUser, handleInviteAuthUser, inviteAuthUserSchema, } from "./tools/auth-users.js";
|
|
114
114
|
import { deletePasskeySchema, handleDeletePasskey, handleListPasskeys, handlePasskeyLoginOptions, handlePasskeyLoginVerify, handlePasskeyRegisterOptions, handlePasskeyRegisterVerify, listPasskeysSchema, passkeyLoginOptionsSchema, passkeyLoginVerifySchema, passkeyRegisterOptionsSchema, passkeyRegisterVerifySchema, } from "./tools/passkeys.js";
|
|
115
115
|
// New tools — project domains
|
|
116
|
-
import { domainsActivateSchema, domainsApplySchema, domainsCheckSchema, domainsDisconnectSchema,
|
|
116
|
+
import { domainsActivateSchema, domainsApplySchema, domainsCheckSchema, domainsDisconnectSchema, domainsConnectSchema, domainsGetSchema, domainsListSchema, domainsRepairSchema, domainsTestReceiveSchema, handleDomainsActivate, handleDomainsApply, handleDomainsCheck, handleDomainsDisconnect, handleDomainsConnect, handleDomainsGet, handleDomainsList, handleDomainsRepair, handleDomainsTestReceive, } from "./tools/domains.js";
|
|
117
117
|
// New tools — email organizations + org checkout
|
|
118
118
|
import { createEmailOrganizationSchema, handleCreateEmailOrganization } from "./tools/create-email-organization.js";
|
|
119
119
|
import { linkWalletToOrganizationSchema, handleLinkWalletToOrganization } from "./tools/link-wallet-to-organization.js";
|
|
@@ -180,8 +180,8 @@ import { deleteSignerSchema, handleDeleteSigner } from "./tools/delete-signer.js
|
|
|
180
180
|
// New tools — service status (public, unauthenticated)
|
|
181
181
|
import { serviceStatusSchema, handleServiceStatus } from "./tools/service-status.js";
|
|
182
182
|
import { serviceHealthSchema, handleServiceHealth } from "./tools/service-health.js";
|
|
183
|
-
// New tools —
|
|
184
|
-
import {
|
|
183
|
+
// New tools — vault (READ-ONLY; the mutating verbs stay CLI-only, see src/tools/repos.ts)
|
|
184
|
+
import { getVaultStatusSchema, handleGetVaultStatus, handleListVaultHeads, handleVerifyVault, listVaultHeadsSchema, verifyVaultSchema, } from "./tools/repos.js";
|
|
185
185
|
// The lossy surface's expand affordance — pairs with every tool that stores a ref.
|
|
186
186
|
import { expandResultSchema, handleExpandResult } from "./tools/expand-result.js";
|
|
187
187
|
import { TOOL_PROFILES, activeProfile, requestedProfileName } from "./tool-profiles.js";
|
|
@@ -467,7 +467,7 @@ server.tool("passkey_login_verify", "Verify a browser WebAuthn assertion and ret
|
|
|
467
467
|
server.tool("list_passkeys", "List the authenticated user's active passkeys.", listPasskeysSchema, async (args) => handleListPasskeys(args));
|
|
468
468
|
server.tool("delete_passkey", "Delete one authenticated-user passkey by id.", deletePasskeySchema, async (args) => handleDeletePasskey(args));
|
|
469
469
|
// --- Project domains ---
|
|
470
|
-
server.tool("
|
|
470
|
+
server.tool("domains_connect", "Connect a custom domain to a project, or change what a connected domain serves: web, email sending, inbound receive, mailbox addresses, and activation. Returns the ProjectDomain with checks, DNS records, and next actions.", domainsConnectSchema, async (args) => handleDomainsConnect(args));
|
|
471
471
|
server.tool("domains_get", "Get one ProjectDomain aggregate with desired, observed, effective, DNS records, checks, and next actions.", domainsGetSchema, async (args) => handleDomainsGet(args));
|
|
472
472
|
server.tool("domains_list", "List all ProjectDomain aggregates for a project.", domainsListSchema, async (args) => handleDomainsList(args));
|
|
473
473
|
server.tool("domains_check", "Re-observe DNS/provider state for a ProjectDomain and return the current checks. Useful as a preflight and drift detector before validation cycles.", domainsCheckSchema, async (args) => handleDomainsCheck(args));
|
|
@@ -513,10 +513,10 @@ server.tool("revoke_project_grant", "Revoke a per-project capability grant by id
|
|
|
513
513
|
// One noun across every agent surface: these three tools teach only `repos`
|
|
514
514
|
// CLI spellings. Only the READ verbs are exposed here. create / delete /
|
|
515
515
|
// rename / snapshot / policy / mirror / gc / access stay CLI-only — see the
|
|
516
|
-
// header of src/tools/
|
|
517
|
-
server.tool("repos_view", "What this machine and the control plane each believe about a repo: the vault record, the activation policy, the local keystore (present? can it sign? does it hold the repo key?), the highest authenticated and materialized pins, pending unvaulted-override journals, and any warnings. This is also the cold-restart entry point — pass project_id with no local state and it resolves the repo for you. Run402 cannot decrypt your
|
|
518
|
-
server.tool("repos_list_heads", "One page of a repo's heads listing — the admitted generations above a fixed anchor, each with its stored-bytes hash. after_generation is the VERIFICATION ANCHOR, not a paging knob: it fixes the generation the listing is verified above and MUST stay identical across every page of one sequence; changing it starts a different listing. limit is required (1..1000). cursor is omitted on the first call and is thereafter the prior page's next_cursor echoed UNCHANGED — it is opaque, so store and echo it, never parse or construct one; a malformed or stale cursor is INVALID_CURSOR and you recover by restarting from after_generation with no cursor. The full page is kept behind a ref and only a window is printed, with shown and total both reported — call expand_result with that ref for the rest. Listing is not verifying: use repos_fsck (or `run402 repos fsck`) to check the chain links.",
|
|
519
|
-
server.tool("repos_fsck", "Verify the repo's head chain from your local authenticated pin up to the newest listed generation, then advance that pin to what was proved. The pin only ever moves forward: verification is monotonic and non-destructive — it rewrites no history and can never lower the pin. It fails CLOSED, and the refusal is the answer: GENERATION_REGRESSION when the vault offers a generation at or below your pin (a rollback), CHAIN_BROKEN on a gap, a missing head, or a link that does not chain, UPGRADE_REQUIRED on a transition this client cannot validate (read-only past it, never skipped), and VERIFICATION_BUDGET_EXCEEDED when the per-call head budget runs out — that last one is a pause, not a failure, because the verified prefix persists and calling again resumes. What verification proves is the chain; what it cannot prove is how long bytes are kept: Retention is an operational promise of the platform, not a cryptographic guarantee against it (the host controls timestamps and bytes). The CLI's `run402 repos fsck` also materializes the ref map and supports `--no-write`/`--mirror`; this tool is the chain-walk half only.",
|
|
516
|
+
// header of src/tools/repos.ts for why each mutating one is excluded.
|
|
517
|
+
server.tool("repos_view", "What this machine and the control plane each believe about a repo: the vault record, the activation policy, the local keystore (present? can it sign? does it hold the repo key?), the highest authenticated and materialized pins, pending unvaulted-override journals, and any warnings. This is also the cold-restart entry point — pass project_id with no local state and it resolves the repo for you. Run402 cannot decrypt your vault or repository history. Deployment artifacts remain a disclosed plaintext custody boundary. Activation requires vault admission by default; an explicit, audited override can bypass it. The output states verbatim, because it is a reviewed product commitment and not a summary you may paraphrase: whole-machine or whole-keystore loss is terminal for vault history until human envelopes ship. Read-only: it signs nothing, publishes nothing, and moves no pin — materializing refs and advancing the pin belongs to `run402 repos fsck`.", getVaultStatusSchema, async (args) => handleGetVaultStatus(args));
|
|
518
|
+
server.tool("repos_list_heads", "One page of a repo's heads listing — the admitted generations above a fixed anchor, each with its stored-bytes hash. after_generation is the VERIFICATION ANCHOR, not a paging knob: it fixes the generation the listing is verified above and MUST stay identical across every page of one sequence; changing it starts a different listing. limit is required (1..1000). cursor is omitted on the first call and is thereafter the prior page's next_cursor echoed UNCHANGED — it is opaque, so store and echo it, never parse or construct one; a malformed or stale cursor is INVALID_CURSOR and you recover by restarting from after_generation with no cursor. The full page is kept behind a ref and only a window is printed, with shown and total both reported — call expand_result with that ref for the rest. Listing is not verifying: use repos_fsck (or `run402 repos fsck`) to check the chain links.", listVaultHeadsSchema, async (args) => handleListVaultHeads(args));
|
|
519
|
+
server.tool("repos_fsck", "Verify the repo's head chain from your local authenticated pin up to the newest listed generation, then advance that pin to what was proved. The pin only ever moves forward: verification is monotonic and non-destructive — it rewrites no history and can never lower the pin. It fails CLOSED, and the refusal is the answer: GENERATION_REGRESSION when the vault offers a generation at or below your pin (a rollback), CHAIN_BROKEN on a gap, a missing head, or a link that does not chain, UPGRADE_REQUIRED on a transition this client cannot validate (read-only past it, never skipped), and VERIFICATION_BUDGET_EXCEEDED when the per-call head budget runs out — that last one is a pause, not a failure, because the verified prefix persists and calling again resumes. What verification proves is the chain; what it cannot prove is how long bytes are kept: Retention is an operational promise of the platform, not a cryptographic guarantee against it (the host controls timestamps and bytes). The CLI's `run402 repos fsck` also materializes the ref map and supports `--no-write`/`--mirror`; this tool is the chain-walk half only.", verifyVaultSchema, async (args) => handleVerifyVault(args));
|
|
520
520
|
server.tool("expand_result", "Fetch more of a result a previous tool showed you only a window of. Tools on this surface truncate the VIEW, never the DATA: when one prints a ref together with shown and total, the full result is held behind that ref and this is how you read the rest of it. Pass the ref plus offset and limit to page through it. Refs live in this server process only — they expire after 30 minutes and only the most recent handful are kept, so re-run the producing tool rather than storing a ref across sessions. A result that carried a secret is never retained and never has a ref, so nothing here can hand one back.", expandResultSchema, async (args) => handleExpandResult(args));
|
|
521
521
|
// Every name in an active profile must have matched a real tool. A profile that
|
|
522
522
|
// silently shrinks because someone renamed a tool is the same class of failure
|