run402 4.37.0 → 4.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/git-remote-run402.mjs +49 -16
- package/lib/command-manifest.mjs +7 -0
- package/lib/gitvault-scaffold.mjs +0 -14
- package/lib/gitvault.mjs +50 -8
- package/lib/org.mjs +70 -0
- package/lib/repos.mjs +108 -6
- package/package.json +1 -1
- package/sdk/dist/index.d.ts +1 -1
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +1 -1
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/namespaces/gitvault.crypto.d.ts +11 -2
- package/sdk/dist/namespaces/gitvault.crypto.d.ts.map +1 -1
- package/sdk/dist/namespaces/gitvault.crypto.js +11 -2
- package/sdk/dist/namespaces/gitvault.crypto.js.map +1 -1
- package/sdk/dist/namespaces/gitvault.d.ts +109 -3
- package/sdk/dist/namespaces/gitvault.d.ts.map +1 -1
- package/sdk/dist/namespaces/gitvault.js +114 -1
- package/sdk/dist/namespaces/gitvault.js.map +1 -1
- package/sdk/dist/namespaces/org.d.ts +18 -1
- package/sdk/dist/namespaces/org.d.ts.map +1 -1
- package/sdk/dist/namespaces/org.js +38 -0
- package/sdk/dist/namespaces/org.js.map +1 -1
- package/sdk/dist/namespaces/org.types.d.ts +16 -0
- package/sdk/dist/namespaces/org.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/projects.d.ts +11 -1
- package/sdk/dist/namespaces/projects.d.ts.map +1 -1
- package/sdk/dist/namespaces/projects.js +16 -0
- package/sdk/dist/namespaces/projects.js.map +1 -1
- package/sdk/dist/namespaces/projects.types.d.ts +7 -0
- package/sdk/dist/namespaces/projects.types.d.ts.map +1 -1
- package/sdk/dist/node/gitvault-address.d.ts +89 -0
- package/sdk/dist/node/gitvault-address.d.ts.map +1 -0
- package/sdk/dist/node/gitvault-address.js +113 -0
- package/sdk/dist/node/gitvault-address.js.map +1 -0
- package/sdk/dist/node/gitvault-creation-journal.d.ts +81 -9
- package/sdk/dist/node/gitvault-creation-journal.d.ts.map +1 -1
- package/sdk/dist/node/gitvault-creation-journal.js +93 -17
- package/sdk/dist/node/gitvault-creation-journal.js.map +1 -1
- package/sdk/dist/node/gitvault-publication.d.ts +13 -0
- package/sdk/dist/node/gitvault-publication.d.ts.map +1 -1
- package/sdk/dist/node/gitvault-publication.js +1 -0
- package/sdk/dist/node/gitvault-publication.js.map +1 -1
- package/sdk/dist/node/gitvault-push-to-create.d.ts +75 -0
- package/sdk/dist/node/gitvault-push-to-create.d.ts.map +1 -0
- package/sdk/dist/node/gitvault-push-to-create.js +132 -0
- package/sdk/dist/node/gitvault-push-to-create.js.map +1 -0
- package/sdk/dist/node/index.d.ts +6 -2
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +8 -1
- package/sdk/dist/node/index.js.map +1 -1
- package/sdk/dist/scoped.d.ts +2 -1
- package/sdk/dist/scoped.d.ts.map +1 -1
- package/sdk/dist/scoped.js +3 -0
- package/sdk/dist/scoped.js.map +1 -1
package/README.md
CHANGED
|
@@ -65,7 +65,9 @@ run402 repos list --org org_1a2b3c
|
|
|
65
65
|
run402 repos delete prj_xyz --force # refuses without --force while the vault holds generations
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
A hosted git remote, encrypted before it leaves the machine — no deploy, no manifest, no app. `origin` is claimed additively — an existing `origin` is never touched, the run402 remote falls back to `run402` instead. `repos create|list|delete` and `gitvault`'s mutating verbs (`init`, `snapshot`, `policy`, `compact`, `prune`) are CLI/OpenClaw-only by design — no MCP tool exists or will exist for them (one-shot recovery receipts, immutable generations, irreversible delete). See `run402 gitvault --help` and `run402 repos --help` for the full surface, and the CLI reference's `gitvault` / `repos` sections for the terminal-loss statement and the progressive backup warning.
|
|
68
|
+
A hosted git remote, encrypted before it leaves the machine — no deploy, no manifest, no app. `origin` is claimed additively — an existing `origin` is never touched, the run402 remote falls back to `run402` instead. `repos create|list|delete|name` and `gitvault`'s mutating verbs (`init`, `snapshot`, `policy`, `compact`, `prune`) are CLI/OpenClaw-only by design — no MCP tool exists or will exist for them (one-shot recovery receipts, immutable generations, irreversible delete). See `run402 gitvault --help` and `run402 repos --help` for the full surface, and the CLI reference's `gitvault` / `repos` sections for the terminal-loss statement and the progressive backup warning.
|
|
69
|
+
|
|
70
|
+
**Named addressing (design D6).** `run402 org slug <slug>` (owner-only, small one-time fee) claims an org's globally-unique, address-form slug, after which `run402::<slug>/<name>` addresses any repo under it — `git push` to a name that doesn't exist yet push-to-creates it. `run402 repos name <name> [--project <id>]` claims the per-org-unique `<name>` half explicitly (no fee); `repos create` claims one automatically, best-effort, when the org already has a slug. Also CLI/SDK-only — no MCP tool.
|
|
69
71
|
|
|
70
72
|
### Allowance
|
|
71
73
|
|
package/git-remote-run402.mjs
CHANGED
|
@@ -28,6 +28,21 @@
|
|
|
28
28
|
* completes the push. One command, no prior `gitvault init`. `git ls-remote`
|
|
29
29
|
* / `fetch` stay pure reads and allocate nothing.
|
|
30
30
|
*
|
|
31
|
+
* NAMED ADDRESSING + PUSH-TO-CREATE (repo-first-onramp task 4, design D6).
|
|
32
|
+
* `run402::<org>/<name>` admits TWO forms in the same slot — id-form
|
|
33
|
+
* (`org_id`/`prj_...`, unchanged: resolved via `r.gitvault.openOrCreate`
|
|
34
|
+
* above) and slug-form (`run402::<org-slug>/<name>`, e.g.
|
|
35
|
+
* `run402::acme/my-notes`) — discriminated by
|
|
36
|
+
* `gitvaultRemoteAddressForm`. A slug-form remote resolves through
|
|
37
|
+
* `r.gitvault.resolveOrCreateAddress`, which ALSO drives push-to-create on a
|
|
38
|
+
* miss (`push` only; `list`/`fetch` pass `allow_create: false`, same "reads
|
|
39
|
+
* never allocate" discipline as the id-form path) and PINS the resolved
|
|
40
|
+
* `repo_id` in this checkout's local git config the first time it resolves
|
|
41
|
+
* (task 4.5) — every later invocation on THIS checkout goes straight to the
|
|
42
|
+
* pinned id, skipping the address resolution round-trip entirely and
|
|
43
|
+
* surviving a later rename of either half. `SLUG_RELEASED` is never
|
|
44
|
+
* auto-followed: it refuses, naming the successor slug.
|
|
45
|
+
*
|
|
31
46
|
* WHICH REPOSITORY (the fail-closed rule). `process.cwd()` is NOT the
|
|
32
47
|
* repository. git identifies the repository with `GIT_DIR`, and during
|
|
33
48
|
* `git clone` cwd is the directory clone was RUN FROM — routinely some other,
|
|
@@ -68,7 +83,7 @@
|
|
|
68
83
|
|
|
69
84
|
import { createInterface } from "node:readline";
|
|
70
85
|
import { getSdk } from "./lib/sdk.mjs";
|
|
71
|
-
import { parseGitvaultRemoteUrl } from "#sdk";
|
|
86
|
+
import { gitvaultRemoteAddressForm, gitvaultSlugReleasedInfo, parseGitvaultRemoteUrl } from "#sdk";
|
|
72
87
|
import { hardenedGit, resolveGitInvocationRepo } from "#sdk/node";
|
|
73
88
|
|
|
74
89
|
const out = (line) => process.stdout.write(`${line}\n`);
|
|
@@ -84,7 +99,11 @@ function oneLine(value) {
|
|
|
84
99
|
function describeError(err) {
|
|
85
100
|
const code = err?.code ?? err?.body?.code ?? null;
|
|
86
101
|
const message = err?.message ?? err?.body?.message ?? String(err);
|
|
87
|
-
|
|
102
|
+
// SLUG_RELEASED is never auto-followed — but the successor slug (design D6)
|
|
103
|
+
// is exactly the fact a human/agent reading stderr needs to act on it.
|
|
104
|
+
const released = gitvaultSlugReleasedInfo(err);
|
|
105
|
+
const suffix = released?.successor_slug ? ` (renamed to "${released.successor_slug}" — update the remote and re-run)` : "";
|
|
106
|
+
return oneLine(code ? `${code}: ${message}${suffix}` : message);
|
|
88
107
|
}
|
|
89
108
|
|
|
90
109
|
/**
|
|
@@ -132,7 +151,10 @@ async function main(argv) {
|
|
|
132
151
|
// `org_id` rides in the parsed address (`run402::<org_id>/<project_id>`),
|
|
133
152
|
// so it costs nothing extra to carry — it is exactly what D2's lazy
|
|
134
153
|
// creation needs to allocate an unresolved vault from `runPush` below, with
|
|
135
|
-
// no separate lookup.
|
|
154
|
+
// no separate lookup. Only meaningful for an ID-FORM address; a slug-form
|
|
155
|
+
// one resolves through `resolveOrCreateAddress` instead (below), which
|
|
156
|
+
// needs no separate org_id at all — the gateway resolves the slug itself.
|
|
157
|
+
const addressForm = gitvaultRemoteAddressForm(address);
|
|
136
158
|
const target = { project_id: address.project_id, org_id: address.org_id };
|
|
137
159
|
let verbosity = 1;
|
|
138
160
|
|
|
@@ -160,25 +182,42 @@ async function main(argv) {
|
|
|
160
182
|
note(`if you meant to restore this vault: git init --bare <dir> && git -C <dir> remote add run402 run402::${address.org_id}/${address.project_id} && git -C <dir> fetch run402 '+refs/heads/*:refs/heads/*'`);
|
|
161
183
|
}
|
|
162
184
|
|
|
163
|
-
/** Open the vault lazily — `capabilities` and `option` must never touch the network. */
|
|
164
|
-
const openVault = async (repoDir) => (await getSdk().gitvault.open(repoDir ? { ...target, repo_dir: repoDir } : target)).vault;
|
|
165
|
-
|
|
166
185
|
/** A 404/absent-vault refusal — the "nothing here yet" shape, never a genuine failure to mask. */
|
|
167
186
|
function isVaultNotFound(err) {
|
|
168
187
|
return err?.status === 404 || err?.code === "RESOURCE_NOT_FOUND" || err?.code === "ROUTE_NOT_FOUND";
|
|
169
188
|
}
|
|
170
189
|
|
|
171
190
|
/**
|
|
172
|
-
* Open the vault
|
|
173
|
-
*
|
|
174
|
-
*
|
|
191
|
+
* Open the vault lazily — `capabilities` and `option` must never touch the
|
|
192
|
+
* network. Dispatches on the address form (design D6): id-form is
|
|
193
|
+
* BYTE-IDENTICAL to before (`gitvault.open` with `{org_id, project_id}`);
|
|
194
|
+
* slug-form resolves (and, on the first successful resolution, PINS
|
|
195
|
+
* `repo_id` in local git state — task 4.5) through
|
|
196
|
+
* `gitvault.resolveOrCreateAddress` with `allow_create: false` — a read
|
|
197
|
+
* never allocates, same discipline the id-form path already had.
|
|
198
|
+
*/
|
|
199
|
+
const openVault = async (repoDir) => {
|
|
200
|
+
if (addressForm === "id") return (await getSdk().gitvault.open(repoDir ? { ...target, repo_dir: repoDir } : target)).vault;
|
|
201
|
+
const result = await getSdk().gitvault.resolveOrCreateAddress({ address, allow_create: false, ...(repoDir ? { repo_dir: repoDir } : {}) });
|
|
202
|
+
return result.handle.vault;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Open the vault, allocating it first when it does not exist yet (D2), and
|
|
207
|
+
* — for a SLUG-form address whose name does not resolve yet —
|
|
208
|
+
* PUSH-TO-CREATE it (design D6, task 4.4/4.5). Used ONLY by `runPush` —
|
|
209
|
+
* `list`/`fetch` stay pure reads and never create anything (see
|
|
210
|
+
* `runList`'s own not-found handling below).
|
|
175
211
|
*
|
|
176
212
|
* Prints the one-shot recovery receipt and the keystore path to stderr the
|
|
177
213
|
* moment allocation happens, per the client-surface spec: an agent reads
|
|
178
214
|
* stderr, and the receipt is worth exactly as many copies as get kept.
|
|
179
215
|
*/
|
|
180
216
|
async function openOrCreateVault(repoDir) {
|
|
181
|
-
const result =
|
|
217
|
+
const result =
|
|
218
|
+
addressForm === "id"
|
|
219
|
+
? await getSdk().gitvault.openOrCreate({ ...target, repo_dir: repoDir })
|
|
220
|
+
: await getSdk().gitvault.resolveOrCreateAddress({ address, repo_dir: repoDir, allow_create: true });
|
|
182
221
|
if (!result.found && result.created) {
|
|
183
222
|
note("");
|
|
184
223
|
note(`vault ${result.handle.repo_id} allocated (genesis ${result.created.genesis_sha256}) — one-shot recovery receipt, keep many copies:`);
|
|
@@ -189,12 +228,6 @@ async function main(argv) {
|
|
|
189
228
|
} catch {
|
|
190
229
|
// Never let a diagnostic line fail a push that already allocated successfully.
|
|
191
230
|
}
|
|
192
|
-
try {
|
|
193
|
-
const { GITVAULT_ALLOCATION_POLICY_ADVISORY } = await import("./lib/gitvault-scaffold.mjs");
|
|
194
|
-
note(GITVAULT_ALLOCATION_POLICY_ADVISORY);
|
|
195
|
-
} catch {
|
|
196
|
-
// Same rule: advisory only, never fatal.
|
|
197
|
-
}
|
|
198
231
|
note("");
|
|
199
232
|
}
|
|
200
233
|
return result.handle.vault;
|
package/lib/command-manifest.mjs
CHANGED
|
@@ -197,6 +197,11 @@ export const COMMAND_MANIFEST = [
|
|
|
197
197
|
{ path: ["org", "get"], positionals: [p("org_id")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["org_gate1"] },
|
|
198
198
|
{ path: ["org", "rename"], positionals: [p("org_id")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["org_gate1", "--name", "Gate"] },
|
|
199
199
|
{ path: ["org", "payout-wallet"], positionals: [p("org_id")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["org_gate1", "--wallet", "0x1111111111111111111111111111111111111111"] },
|
|
200
|
+
// repo-first-onramp task 4.1 (design D6). `--org` (not a positional org_id
|
|
201
|
+
// like rename/payout-wallet above) goes through resolveOrg's SHAPE
|
|
202
|
+
// validation (a real UUID) — "org_gate1" fails that locally, so this needs
|
|
203
|
+
// the same UUID-shaped fixture `org use` below already established.
|
|
204
|
+
{ path: ["org", "slug"], positionals: [p("slug")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["acme", "--org", "11111111-2222-3333-4444-555555555555"] },
|
|
200
205
|
{ path: ["org", "whoami"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: [] },
|
|
201
206
|
{ path: ["org", "audit"], positionals: [p("org_id")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["org_gate1"] },
|
|
202
207
|
{ path: ["org", "use"], positionals: [p("org_id")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["11111111-2222-3333-4444-555555555555"] },
|
|
@@ -274,6 +279,8 @@ export const COMMAND_MANIFEST = [
|
|
|
274
279
|
{ path: ["repos", "create"], positionals: [p("name")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["my-notes"], runStyle: "sub", skipBehavioral: "provisions a project, allocates a vault, and scaffolds a real git remote into cwd" },
|
|
275
280
|
{ path: ["repos", "list"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub", skipBehavioral: "cross-references live projects against their live gitvault status, one call per project" },
|
|
276
281
|
{ path: ["repos", "delete"], positionals: [], projectScoped: true, legacyPositionalProject: true, minimalArgs: [], runStyle: "sub", skipBehavioral: "irreversibly deletes a project after reading its live vault generation count" },
|
|
282
|
+
// repo-first-onramp task 4.2 (design D6): explicit address-form name claim.
|
|
283
|
+
{ path: ["repos", "name"], positionals: [p("name")], projectScoped: true, legacyPositionalProject: false, minimalArgs: ["my-notes"], runStyle: "sub", skipBehavioral: "claims a per-org-unique repo name against a live project" },
|
|
277
284
|
{ path: ["errors"], positionals: [p("fingerprint_id", { required: false })], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "merged" },
|
|
278
285
|
|
|
279
286
|
// ── jobs ─────────────────────────────────────────────────────────────────
|
|
@@ -19,20 +19,6 @@
|
|
|
19
19
|
import { getSdk } from "./sdk.mjs";
|
|
20
20
|
import { resolveOwningOrgId } from "./org-context.mjs";
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
* The interim allocation→policy advisory (repo-first-onramp D3, stated as an
|
|
24
|
-
* interim). TODAY the platform sets `gitvault_policy: required` at allocation
|
|
25
|
-
* — the decoupling (allocation leaving the policy unset) is design D3's
|
|
26
|
-
* gateway half and ships in a later release (task 3.1). Until it does, every
|
|
27
|
-
* client-side path that allocates a vault prints this line so the policy flip
|
|
28
|
-
* is never a silent side effect of a push or a create. Faithful over flattering:
|
|
29
|
-
* documenting the designed future as the present is the breach; this line is
|
|
30
|
-
* the truth. DELETE this export (and its four call sites) when the gateway
|
|
31
|
-
* decoupling ships.
|
|
32
|
-
*/
|
|
33
|
-
export const GITVAULT_ALLOCATION_POLICY_ADVISORY =
|
|
34
|
-
"note: allocation currently sets gitvault_policy to 'required' — from now on a deploy must present a vaulted capture (produced automatically by `run402 deploy apply` on any machine holding this keystore). Opt out with `run402 gitvault policy grandfathered --reason \"<why>\"`. A later release decouples allocation from the deploy gate (design D3).";
|
|
35
|
-
|
|
36
22
|
/**
|
|
37
23
|
* @param {object} options
|
|
38
24
|
* @param {string} [options.repoDir] Working tree to scaffold. Defaults to `process.cwd()`.
|
package/lib/gitvault.mjs
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
import { readFileSync } from "node:fs";
|
|
20
20
|
import { resolveProjectId } from "./config.mjs";
|
|
21
21
|
import { resolveOwningOrgId } from "./org-context.mjs";
|
|
22
|
-
import { GITVAULT_ALLOCATION_POLICY_ADVISORY } from "./gitvault-scaffold.mjs";
|
|
23
22
|
import { getSdk } from "./sdk.mjs";
|
|
24
23
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
25
24
|
import {
|
|
@@ -70,8 +69,12 @@ Subcommands:
|
|
|
70
69
|
deploy — a vault-only project snapshots for months without one.
|
|
71
70
|
Against a project with no vault yet, this ALLOCATES one inline
|
|
72
71
|
(the six-stage creation, same as \`init\`) before publishing — one
|
|
73
|
-
command, no prior \`gitvault init\`.
|
|
74
|
-
|
|
72
|
+
command, no prior \`gitvault init\`. When --repo/--project are
|
|
73
|
+
both omitted and the local run402/origin remote is a slug-form
|
|
74
|
+
address (run402::<org-slug>/<name>), PUSH-TO-CREATES through it
|
|
75
|
+
instead (design D6) — same as pushing that name with \`git\`. The
|
|
76
|
+
one-shot recovery receipt and keystore path print to stderr the
|
|
77
|
+
moment that happens.
|
|
75
78
|
Before reporting a snapshot as landed the SDK compares finalization
|
|
76
79
|
receipts against the expected manifest and reads the admitted head
|
|
77
80
|
back from storage; a 200 alone is never enough. \`push\` is a
|
|
@@ -284,7 +287,6 @@ async function init(args) {
|
|
|
284
287
|
);
|
|
285
288
|
if (result.remote) console.error(`remote '${result.remote.name}' -> ${result.remote.url} (${result.remote.reason})`);
|
|
286
289
|
if (remoteSkipped) console.error(`remote not added: ${remoteSkipped}`);
|
|
287
|
-
if (!result.deduplicated) console.error(GITVAULT_ALLOCATION_POLICY_ADVISORY);
|
|
288
290
|
// The recovery receipt is integrity data, not a secret, and it is worth
|
|
289
291
|
// exactly as much as the number of copies you keep. It is persisted into
|
|
290
292
|
// the keystore automatically; say where, because "keep many copies" is
|
|
@@ -372,6 +374,15 @@ async function status(args) {
|
|
|
372
374
|
if (s.remote) {
|
|
373
375
|
console.error(`remote '${s.remote.name}': ${s.remote.url}${s.remote.matches ? "" : " ← points at a DIFFERENT project than this status"}`);
|
|
374
376
|
}
|
|
377
|
+
// The id-pinning state (design D6, task 4.5): a slug-form remote pins
|
|
378
|
+
// repo_id in local git state the first time it resolves; id-form pins
|
|
379
|
+
// nothing (it needs no pin — see resolveGitvaultAddress's doc comment).
|
|
380
|
+
if (s.pinned) {
|
|
381
|
+
console.error(
|
|
382
|
+
`pinned: repo_id ${s.pinned.repo_id}` +
|
|
383
|
+
(s.pinned.resolved_from ? ` (resolved from run402::${s.pinned.resolved_from.org_slug}/${s.pinned.resolved_from.repo_name})` : ""),
|
|
384
|
+
);
|
|
385
|
+
}
|
|
375
386
|
if (s.refs) {
|
|
376
387
|
const names = Object.keys(s.refs).sort();
|
|
377
388
|
console.error(names.length === 0 ? "refs: (none yet)" : `refs (${names.length}):`);
|
|
@@ -398,6 +409,33 @@ async function status(args) {
|
|
|
398
409
|
* only the dispatched SUBCOMMAND name changed (see `run()` below, where
|
|
399
410
|
* `gitvault push` survives one release as a deprecation-warning alias).
|
|
400
411
|
*/
|
|
412
|
+
/**
|
|
413
|
+
* D6 (repo-first-onramp task 4): when neither `--repo` nor `--project` was
|
|
414
|
+
* given explicitly, look at the local `run402`/`origin` remote (in that
|
|
415
|
+
* order, mirroring `scaffoldRemote`'s own naming) and, if it is a SLUG-form
|
|
416
|
+
* address (`run402::<org-slug>/<name>`), return the parsed address so
|
|
417
|
+
* `snapshot` can push-to-create through it — the same address-form
|
|
418
|
+
* resolution `git push` drives via the remote helper. `null` for an
|
|
419
|
+
* id-form remote, no remote at all, or an explicit `--repo`/`--project`.
|
|
420
|
+
*/
|
|
421
|
+
async function detectSlugFormRemote(a, repoDir) {
|
|
422
|
+
if (flagValue(a, "--repo") != null || flagValue(a, "--project") != null) return null;
|
|
423
|
+
const { hardenedGit } = await import("#sdk/node");
|
|
424
|
+
const { parseGitvaultRemoteUrl, gitvaultRemoteAddressForm } = await import("#sdk");
|
|
425
|
+
for (const name of ["run402", "origin"]) {
|
|
426
|
+
let url;
|
|
427
|
+
try {
|
|
428
|
+
url = (await hardenedGit(repoDir, ["remote", "get-url", name])).text().trim();
|
|
429
|
+
} catch {
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (!url) continue;
|
|
433
|
+
const address = parseGitvaultRemoteUrl(url);
|
|
434
|
+
if (address && gitvaultRemoteAddressForm(address) === "slug") return address;
|
|
435
|
+
}
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
|
|
401
439
|
async function snapshot(args) {
|
|
402
440
|
const a = normalizeArgv(args);
|
|
403
441
|
const valueFlags = [...COMMON_VALUE_FLAGS, "--message"];
|
|
@@ -406,14 +444,19 @@ async function snapshot(args) {
|
|
|
406
444
|
min: 0, max: 0, command: "run402 gitvault snapshot", missing: "",
|
|
407
445
|
});
|
|
408
446
|
const message = flagValue(a, "--message");
|
|
409
|
-
const
|
|
447
|
+
const repoDir = process.cwd();
|
|
448
|
+
const address = await detectSlugFormRemote(a, repoDir);
|
|
410
449
|
// D2: lazily allocate the vault on first push when there is a project to
|
|
411
450
|
// resolve the owning org from — the same resolution `gitvault init` uses.
|
|
412
451
|
// `--repo`-only addressing has nothing to create FROM (no project_id), so
|
|
413
|
-
// it is skipped there, matching `open()`'s own precedence.
|
|
414
|
-
|
|
452
|
+
// it is skipped there, matching `open()`'s own precedence. Skipped
|
|
453
|
+
// entirely for a slug-form remote (`address` above) — that resolves
|
|
454
|
+
// through the address, not a project_id, and needs no separate org_id.
|
|
455
|
+
const target = address ? { repo_dir: repoDir } : vaultTarget(a);
|
|
456
|
+
const orgId = !address && target.project_id ? await resolveOwningOrgId(target.project_id) : null;
|
|
415
457
|
const opts = {
|
|
416
458
|
...target,
|
|
459
|
+
...(address ? { address } : {}),
|
|
417
460
|
...(orgId ? { org_id: orgId } : {}),
|
|
418
461
|
// The gitvault_commit line is progress, not payload: print it the moment
|
|
419
462
|
// the snapshot exists, well before the publication round-trips finish, so
|
|
@@ -428,7 +471,6 @@ async function snapshot(args) {
|
|
|
428
471
|
console.error(`vault allocated (genesis ${created.genesis_sha256}) — one-shot recovery receipt, keep many copies:`);
|
|
429
472
|
console.error(JSON.stringify(created.recovery_receipt));
|
|
430
473
|
await printKeystoreLocation();
|
|
431
|
-
console.error(GITVAULT_ALLOCATION_POLICY_ADVISORY);
|
|
432
474
|
console.error("");
|
|
433
475
|
},
|
|
434
476
|
};
|
package/lib/org.mjs
CHANGED
|
@@ -30,6 +30,7 @@ Usage:
|
|
|
30
30
|
run402 org get <org_id>
|
|
31
31
|
run402 org rename <org_id> --name <display_name> (or: --clear to remove the label)
|
|
32
32
|
run402 org payout-wallet <org_id> --wallet <wallet_address> (or: --clear to remove the explicit default)
|
|
33
|
+
run402 org slug <slug> [--org <org_id>]
|
|
33
34
|
run402 org whoami
|
|
34
35
|
run402 org use <org_id>
|
|
35
36
|
run402 org current
|
|
@@ -53,6 +54,9 @@ Subcommands:
|
|
|
53
54
|
list Orgs you are a member of
|
|
54
55
|
get Read one org (label + tier/lease + your role)
|
|
55
56
|
rename Set or clear an org's display label (owner-only)
|
|
57
|
+
slug Claim or rename the org's globally-unique, address-form slug
|
|
58
|
+
(owner-only). A genesis claim spends a one-time claim fee; a
|
|
59
|
+
rename releases the old slug into a ~90-day cooldown.
|
|
56
60
|
use Select the current org for this wallet profile
|
|
57
61
|
current Report the resolved current org and where it came from
|
|
58
62
|
clear Clear this wallet profile's org selection
|
|
@@ -120,6 +124,26 @@ Legacy (still supported):
|
|
|
120
124
|
|
|
121
125
|
Owner-only + step-up gated. Pass --clear (or an empty display_name) to remove
|
|
122
126
|
the label. Output includes the updated tier and lease timestamps.
|
|
127
|
+
`,
|
|
128
|
+
slug: `run402 org slug — claim or rename the org's address-form slug
|
|
129
|
+
|
|
130
|
+
Usage:
|
|
131
|
+
run402 org slug <slug> [--org <org_id>] [--idempotency-key <key>]
|
|
132
|
+
|
|
133
|
+
The slug is a globally-unique, claimable, address-form handle for the org
|
|
134
|
+
(repo-first-onramp design D6) — the <org-slug> half of a named repo address
|
|
135
|
+
run402::<org-slug>/<name>. Grammar: lowercase [a-z0-9-], no leading/trailing/
|
|
136
|
+
double hyphen, max 39 chars. Owner-only.
|
|
137
|
+
|
|
138
|
+
A genesis claim (the org had no prior slug) spends a one-time claim fee off
|
|
139
|
+
the org's balance. A rename is free but releases the OLD slug into a ~90-day
|
|
140
|
+
cooldown: it stops resolving, with a typed SLUG_RELEASED refusal naming the
|
|
141
|
+
new slug as successor — there is no redirect, so update every remote and
|
|
142
|
+
address that still names the old one.
|
|
143
|
+
|
|
144
|
+
This is a paid, side-effecting mutation and requires Idempotency-Key; the SDK
|
|
145
|
+
generates one automatically unless --idempotency-key is passed, so a retried
|
|
146
|
+
call after a dropped response can never double-bill.
|
|
123
147
|
`,
|
|
124
148
|
"payout-wallet": `run402 org payout-wallet — set or clear the tenant route payout wallet
|
|
125
149
|
|
|
@@ -413,6 +437,51 @@ async function payoutWallet(args) {
|
|
|
413
437
|
}
|
|
414
438
|
}
|
|
415
439
|
|
|
440
|
+
/**
|
|
441
|
+
* `run402 org slug <slug>` — claim or rename the org's address-form slug
|
|
442
|
+
* (repo-first-onramp design D6). Owner-only, and a genesis claim spends a
|
|
443
|
+
* one-time claim fee — this is a PAID, side-effecting mutation, so it
|
|
444
|
+
* requires `Idempotency-Key`; the SDK generates one client-side when
|
|
445
|
+
* `--idempotency-key` is omitted, so a retried call after a dropped response
|
|
446
|
+
* can never double-bill.
|
|
447
|
+
*/
|
|
448
|
+
async function slug(args) {
|
|
449
|
+
const a = normalizeArgv(args);
|
|
450
|
+
const valueFlags = ["--org", "--idempotency-key"];
|
|
451
|
+
assertKnownFlags(a, [...valueFlags, "--help", "-h"], valueFlags);
|
|
452
|
+
const [newSlug] = requirePositionalCount(a, valueFlags, {
|
|
453
|
+
min: 1,
|
|
454
|
+
max: 1,
|
|
455
|
+
command: "run402 org slug <slug> [--org <org_id>]",
|
|
456
|
+
missing: "Missing <slug>.",
|
|
457
|
+
});
|
|
458
|
+
const org = await resolveOrg(a, { cmd: "org" });
|
|
459
|
+
if (!org) {
|
|
460
|
+
fail({
|
|
461
|
+
code: "ORG_UNRESOLVED",
|
|
462
|
+
message: "Could not resolve which organization to claim this slug for.",
|
|
463
|
+
hint: "Pass --org <org_id>, or select one first with `run402 org use <id>`.",
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
const idempotencyKey = flagValue(a, "--idempotency-key");
|
|
467
|
+
try {
|
|
468
|
+
const result = await getSdk().org(org.orgId).claimSlug(newSlug, idempotencyKey != null ? { idempotencyKey } : {});
|
|
469
|
+
console.log(JSON.stringify(result, null, 2));
|
|
470
|
+
if (result.created) {
|
|
471
|
+
console.error(`slug "${result.slug}" claimed for ${org.orgId} — a one-time claim fee was debited from the org's balance.`);
|
|
472
|
+
} else if (result.previous_slug && result.previous_slug !== result.slug) {
|
|
473
|
+
console.error(
|
|
474
|
+
`org ${org.orgId} renamed from "${result.previous_slug}" to "${result.slug}" — no fee. ` +
|
|
475
|
+
`"${result.previous_slug}" now enters its ~90-day release cooldown: it stops resolving with a typed SLUG_RELEASED refusal (naming "${result.slug}" as the successor), never a redirect. Update every remote and address that still names it.`,
|
|
476
|
+
);
|
|
477
|
+
} else {
|
|
478
|
+
console.error(`"${result.slug}" was already ${org.orgId}'s current slug — nothing changed, no fee.`);
|
|
479
|
+
}
|
|
480
|
+
} catch (err) {
|
|
481
|
+
reportSdkError(err);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
416
485
|
async function audit(args) {
|
|
417
486
|
const a = normalizeArgv(args);
|
|
418
487
|
const valueFlags = ["--limit", "--after", "--before"];
|
|
@@ -630,6 +699,7 @@ export async function run(sub, args) {
|
|
|
630
699
|
case "get": await get(args); break;
|
|
631
700
|
case "rename": await rename(args); break;
|
|
632
701
|
case "payout-wallet": await payoutWallet(args); break;
|
|
702
|
+
case "slug": await slug(args); break;
|
|
633
703
|
case "whoami": await whoami(args); break;
|
|
634
704
|
case "use": await use(args); break;
|
|
635
705
|
case "current": await current(args); break;
|
package/lib/repos.mjs
CHANGED
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
import { getSdk } from "./sdk.mjs";
|
|
36
36
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
37
37
|
import { withAutoApprove } from "./operator.mjs";
|
|
38
|
-
import { allowanceAuthHeaders, isCoreApiTarget } from "./config.mjs";
|
|
38
|
+
import { allowanceAuthHeaders, isCoreApiTarget, resolveProjectId } from "./config.mjs";
|
|
39
39
|
import { loadLiveControlPlaneSession } from "../core-dist/control-plane-session.js";
|
|
40
40
|
import { resolveOrgId, resolveOwningOrgId } from "./org-context.mjs";
|
|
41
41
|
import { nextAction } from "./next-actions.mjs";
|
|
42
42
|
import { printKeystoreLocation } from "./gitvault.mjs";
|
|
43
|
-
import {
|
|
43
|
+
import { gitvaultRemoteUrlForRepo } from "#sdk";
|
|
44
44
|
import {
|
|
45
45
|
normalizeArgv,
|
|
46
46
|
hasHelp,
|
|
@@ -57,21 +57,30 @@ Usage:
|
|
|
57
57
|
run402 repos create <name> [--org <org_id>] [--dir <path>] [--tier <tier>]
|
|
58
58
|
run402 repos list [--org <org_id>]
|
|
59
59
|
run402 repos delete <project_id> [--force]
|
|
60
|
+
run402 repos name <name> [--project <id>]
|
|
60
61
|
|
|
61
62
|
Subcommands:
|
|
62
63
|
create Provision a project, ALLOCATE its vault (mints key material and a
|
|
63
64
|
one-shot recovery receipt), and scaffold the run402 remote —
|
|
64
65
|
origin when free, run402 when taken (D1). No deploy plan, no
|
|
65
66
|
release, nothing deployed: the vault-only track (design D8), for a
|
|
66
|
-
project that only ever hosts encrypted source.
|
|
67
|
+
project that only ever hosts encrypted source. When the owning org
|
|
68
|
+
has a slug (run402 org slug), also claims the project's address-
|
|
69
|
+
form repo name (best-effort — a name collision or missing slug
|
|
70
|
+
never fails the command) and prints the run402::<slug>/<name>
|
|
71
|
+
address (design D6).
|
|
67
72
|
list The organization's vault-bearing projects — those with an
|
|
68
73
|
allocated vault, whether or not they have ever deployed. Not
|
|
69
|
-
every project in the org; ones with no vault are omitted.
|
|
74
|
+
every project in the org; ones with no vault are omitted. Shows
|
|
75
|
+
the run402::<slug>/<name> address for a repo that has claimed one.
|
|
70
76
|
delete Delete the project and everything in it (database, functions,
|
|
71
77
|
subdomains, mailbox, secrets). REFUSES while the vault holds any
|
|
72
78
|
admitted generation unless --force is passed — this is
|
|
73
79
|
irreversible and destroys the vault's entire encrypted history
|
|
74
80
|
along with everything else.
|
|
81
|
+
name Claim or rename the project's per-org-unique, address-form name
|
|
82
|
+
(design D6) — the <name> half of run402::<org-slug>/<name>. No
|
|
83
|
+
fee, unlike the org slug. Same authority as renaming the project.
|
|
75
84
|
|
|
76
85
|
Options:
|
|
77
86
|
--org <org_id> create/list: the owning organization. create resolves it
|
|
@@ -89,6 +98,8 @@ Options:
|
|
|
89
98
|
derived from the name)
|
|
90
99
|
--force delete: proceed even though the vault holds generations
|
|
91
100
|
that would be permanently and irrecoverably lost
|
|
101
|
+
--project <id> name: project to claim the repo name for (default: the
|
|
102
|
+
active project)
|
|
92
103
|
--json No-op: stdout is already JSON.
|
|
93
104
|
|
|
94
105
|
There is no separate gitvault price: bytes count against the same
|
|
@@ -98,6 +109,7 @@ organization-pooled storage budget every project already has.
|
|
|
98
109
|
const CREATE_VALUE_FLAGS = ["--org", "--dir", "--tier", "--idempotency-key"];
|
|
99
110
|
const LIST_VALUE_FLAGS = ["--org"];
|
|
100
111
|
const DELETE_VALUE_FLAGS = ["--project"];
|
|
112
|
+
const NAME_VALUE_FLAGS = ["--project"];
|
|
101
113
|
|
|
102
114
|
function validateProjectName(name) {
|
|
103
115
|
if (name === "") {
|
|
@@ -124,6 +136,24 @@ function validateProjectName(name) {
|
|
|
124
136
|
}
|
|
125
137
|
}
|
|
126
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Best-effort slugify for the address-form repo name (design D6's grammar:
|
|
141
|
+
* lowercase [a-z0-9-], no leading/trailing/double hyphen, <=63 chars). The
|
|
142
|
+
* free-text project display name (`repos create <name>`'s positional) is
|
|
143
|
+
* NOT already in this charset, so `create` derives a candidate rather than
|
|
144
|
+
* sending the raw name straight to the claim route and failing on the first
|
|
145
|
+
* space or capital letter.
|
|
146
|
+
*/
|
|
147
|
+
function slugifyRepoName(name) {
|
|
148
|
+
return name
|
|
149
|
+
.toLowerCase()
|
|
150
|
+
.replace(/[^a-z0-9-]+/g, "-")
|
|
151
|
+
.replace(/-+/g, "-")
|
|
152
|
+
.replace(/^-+|-+$/g, "")
|
|
153
|
+
.slice(0, 63)
|
|
154
|
+
.replace(/-+$/g, "");
|
|
155
|
+
}
|
|
156
|
+
|
|
127
157
|
async function create(args) {
|
|
128
158
|
const a = normalizeArgv(args);
|
|
129
159
|
assertKnownFlags(a, [...CREATE_VALUE_FLAGS, "--help", "-h"], CREATE_VALUE_FLAGS);
|
|
@@ -178,9 +208,29 @@ async function create(args) {
|
|
|
178
208
|
project_id: provisioned.project_id,
|
|
179
209
|
repo_dir: dir,
|
|
180
210
|
});
|
|
211
|
+
// Best-effort address-form name claim (design D6): when the owning org
|
|
212
|
+
// has a slug, name this repo so it is reachable as
|
|
213
|
+
// run402::<slug>/<name> too — never fails `create` itself. A collision,
|
|
214
|
+
// a missing slug, or any other refusal just means no address this time;
|
|
215
|
+
// `run402 repos name <name>` claims it explicitly later.
|
|
216
|
+
let address = null;
|
|
217
|
+
try {
|
|
218
|
+
const orgRecord = await getSdk().org(effectiveOrgId).get();
|
|
219
|
+
if (orgRecord.slug) {
|
|
220
|
+
const candidate = slugifyRepoName(name);
|
|
221
|
+
if (candidate) {
|
|
222
|
+
const named = await getSdk().projects.setRepoName(provisioned.project_id, candidate);
|
|
223
|
+
address = gitvaultRemoteUrlForRepo(orgRecord.slug, named.repo_name);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
} catch (err) {
|
|
227
|
+
console.error(`repo name not claimed (non-fatal): ${err?.message ?? String(err)}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
181
230
|
const out = {
|
|
182
231
|
project_id: provisioned.project_id,
|
|
183
232
|
repo_id: vault.repo_id,
|
|
233
|
+
address,
|
|
184
234
|
remote: vault.remote,
|
|
185
235
|
deduplicated: vault.deduplicated,
|
|
186
236
|
genesis_sha256: vault.genesis_sha256,
|
|
@@ -193,11 +243,11 @@ async function create(args) {
|
|
|
193
243
|
`project ${provisioned.project_id} provisioned; vault ${vault.repo_id} ` +
|
|
194
244
|
(vault.deduplicated ? "already existed — nothing was re-allocated" : `allocated (genesis ${vault.genesis_sha256})`),
|
|
195
245
|
);
|
|
246
|
+
if (address) console.error(`address: ${address}`);
|
|
196
247
|
if (vault.remote) console.error(`remote '${vault.remote.name}' -> ${vault.remote.url} (${vault.remote.reason})`);
|
|
197
248
|
console.error("");
|
|
198
249
|
console.error(vault.terminal_loss_statement);
|
|
199
250
|
await printKeystoreLocation();
|
|
200
|
-
if (!vault.deduplicated) console.error(GITVAULT_ALLOCATION_POLICY_ADVISORY);
|
|
201
251
|
console.error("");
|
|
202
252
|
console.error("nothing was deployed — this is a vault-only repo. Deploy later with `run402 deploy apply`, or never.");
|
|
203
253
|
} catch (err) {
|
|
@@ -246,8 +296,21 @@ async function list(args) {
|
|
|
246
296
|
genesis_admitted_at: status.vault.genesis_admitted_at,
|
|
247
297
|
});
|
|
248
298
|
}
|
|
249
|
-
|
|
299
|
+
// The org's slug, when claimed (design D6) — printed so a human/agent can
|
|
300
|
+
// construct run402::<slug>/<name> addresses by hand. There is deliberately
|
|
301
|
+
// no per-project `address` field here yet: the gateway has no bulk (or
|
|
302
|
+
// even single) READ for a project's claimed repo_name today, only the
|
|
303
|
+
// WRITE route (`POST /projects/v1/:id/repo-name`) — adding one is gateway
|
|
304
|
+
// work, out of scope for this client-only change (see the final report).
|
|
305
|
+
let orgSlug = null;
|
|
306
|
+
try {
|
|
307
|
+
orgSlug = (await getSdk().org(orgId).get()).slug;
|
|
308
|
+
} catch {
|
|
309
|
+
// Best-effort — `list` must not fail over an org-slug lookup.
|
|
310
|
+
}
|
|
311
|
+
console.log(JSON.stringify({ org_id: orgId, org_slug: orgSlug, repos }, null, 2));
|
|
250
312
|
console.error(`${repos.length} vault-bearing project(s) of ${projects.length} total in this organization`);
|
|
313
|
+
if (orgSlug) console.error(`org slug: ${orgSlug} — a repo with a claimed address-form name is reachable at run402::${orgSlug}/<name>`);
|
|
251
314
|
}
|
|
252
315
|
|
|
253
316
|
async function del(args) {
|
|
@@ -299,6 +362,41 @@ async function del(args) {
|
|
|
299
362
|
}
|
|
300
363
|
}
|
|
301
364
|
|
|
365
|
+
/**
|
|
366
|
+
* `run402 repos name <name> [--project <id>]` — the explicit address-form
|
|
367
|
+
* claim (design D6, task 4.2): a project gets its per-org-unique `<name>`
|
|
368
|
+
* half of `run402::<org-slug>/<name>` either at push-to-create time or here.
|
|
369
|
+
*/
|
|
370
|
+
async function name(args) {
|
|
371
|
+
const a = normalizeArgv(args);
|
|
372
|
+
assertKnownFlags(a, [...NAME_VALUE_FLAGS, "--help", "-h"], NAME_VALUE_FLAGS);
|
|
373
|
+
const [repoName] = requirePositionalCount(a, NAME_VALUE_FLAGS, {
|
|
374
|
+
min: 1, max: 1, command: "run402 repos name <name> [--project <id>]", missing: "run402 repos name <name>: a name is required",
|
|
375
|
+
});
|
|
376
|
+
const projectId = resolveProjectId(flagValue(a, "--project"));
|
|
377
|
+
try {
|
|
378
|
+
const result = await getSdk().projects.setRepoName(projectId, repoName);
|
|
379
|
+
let address = null;
|
|
380
|
+
try {
|
|
381
|
+
const owningOrg = await resolveOwningOrgId(projectId);
|
|
382
|
+
const orgSlug = owningOrg ? (await getSdk().org(owningOrg).get()).slug : null;
|
|
383
|
+
if (orgSlug) address = gitvaultRemoteUrlForRepo(orgSlug, result.repo_name);
|
|
384
|
+
} catch {
|
|
385
|
+
// The claim itself already succeeded — a failed address-preview lookup is never fatal.
|
|
386
|
+
}
|
|
387
|
+
console.log(JSON.stringify({ ...result, address }, null, 2));
|
|
388
|
+
console.error(
|
|
389
|
+
result.previous_repo_name && result.previous_repo_name !== result.repo_name
|
|
390
|
+
? `renamed from "${result.previous_repo_name}" to "${result.repo_name}"`
|
|
391
|
+
: `name "${result.repo_name}" claimed for ${projectId}`,
|
|
392
|
+
);
|
|
393
|
+
if (address) console.error(`address: ${address}`);
|
|
394
|
+
else console.error("this org has no slug yet — claim one with `run402 org slug <slug>` to get a full run402::<slug>/<name> address");
|
|
395
|
+
} catch (err) {
|
|
396
|
+
reportSdkError(err);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
302
400
|
export async function run(sub, args) {
|
|
303
401
|
const argv = Array.isArray(args) ? args : [];
|
|
304
402
|
if (!sub || hasHelp([sub, ...argv])) {
|
|
@@ -318,6 +416,10 @@ export async function run(sub, args) {
|
|
|
318
416
|
await del(argv);
|
|
319
417
|
break;
|
|
320
418
|
}
|
|
419
|
+
case "name": {
|
|
420
|
+
await name(argv);
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
321
423
|
default:
|
|
322
424
|
failUnknownSubcommand("repos", sub, {
|
|
323
425
|
hint: "Run `run402 repos --help` for usage.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "run402",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.38.0",
|
|
4
4
|
"description": "CLI for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/sdk/dist/index.d.ts
CHANGED
|
@@ -363,6 +363,6 @@ export type * from "./namespaces/wallets.js";
|
|
|
363
363
|
export * from "./namespaces/gitvault.crypto.js";
|
|
364
364
|
export type * from "./namespaces/gitvault.crypto.js";
|
|
365
365
|
export type * from "./namespaces/gitvault.types.js";
|
|
366
|
-
export { Gitvault, gitvaultRemoteUrl, parseGitvaultRemoteUrl, GITVAULT_LOSS_WARNING_THRESHOLDS, gitvaultLossWarningTrip, gitvaultLossWarningTripped, gitvaultLossWarningMessage, } from "./namespaces/gitvault.js";
|
|
366
|
+
export { Gitvault, gitvaultRemoteUrl, gitvaultRemoteUrlForRepo, parseGitvaultRemoteUrl, gitvaultRemoteAddressForm, gitvaultSlugReleasedInfo, GITVAULT_LOSS_WARNING_THRESHOLDS, gitvaultLossWarningTrip, gitvaultLossWarningTripped, gitvaultLossWarningMessage, } from "./namespaces/gitvault.js";
|
|
367
367
|
export type * from "./namespaces/gitvault.js";
|
|
368
368
|
//# sourceMappingURL=index.d.ts.map
|