@dvmkit/dvmctl 0.3.4-rc.1 → 0.3.5-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/dvmctl.js +5 -5
- package/package.json +1 -1
- package/skills/build-dvm/SKILL.md +28 -88
- package/skills/build-dvm/deploying.md +42 -0
- package/skills/build-dvm/new-builder.md +41 -0
- package/skills/build-dvm/operating.md +31 -0
- package/skills/build-dvm/recovery.md +39 -0
- package/skills/build-dvm/references/lightning-credit-test.md +37 -0
- package/skills/build-dvm/references/local-cashu-test.md +7 -2
- package/skills/build-dvm/references/local-tempo-test.md +13 -2
- package/skills/build-dvm/references/local-x402-test.md +13 -2
- package/skills/build-dvm/retirement.md +31 -0
- package/skills/build-dvm/testing.md +33 -0
- package/skills/build-dvm/references/configure-context.md +0 -273
- package/skills/build-dvm/references/operating-feedback.md +0 -153
- package/skills/build-dvm/references/patterns-auth.md +0 -390
- package/skills/build-dvm/references/payment-rails.md +0 -11
- package/skills/build-dvm/references/pricing-credit.md +0 -155
- package/skills/build-dvm/references/running-deployment.md +0 -233
- package/skills/build-dvm/references/sdk-reference.md +0 -47
- package/skills/build-dvm/references/testing.md +0 -181
package/package.json
CHANGED
|
@@ -1,107 +1,47 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: build-dvm
|
|
3
|
-
description: Build a
|
|
4
|
-
compatibility: Node.js 22+, npm, the invited
|
|
3
|
+
description: Build and operate a Digital Vending Machine with dvmkit. Use when asked to turn an idea into a paid HTTPS service, implement a capability, test payments or Lightning-funded credit, deploy or update a DVM, inspect earnings or health, recover a failed operation, or retire a service. Do not use for dvmkit platform or SDK internals, or for using someone else's DVM except to test the service being built.
|
|
4
|
+
compatibility: Node.js 22+, npm, the invited @dvmkit/dvmctl release, @dvmkit/sdk@0.2.1-rc.9, and @dvmkit/dvm-cli@0.3.0. Docker is needed for container builds or an owned local Cashu test mint.
|
|
5
5
|
allowed-tools: Bash Read Write Edit Glob Grep
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Build a DVM
|
|
8
|
+
# Build and operate a DVM
|
|
9
9
|
|
|
10
|
-
Use
|
|
10
|
+
Use `dvmctl` to manage the service and `@dvmkit/sdk` to implement its capabilities. Use the caller CLI, `dvm`, when testing the service as a customer. Keep its test wallet separate from the builder's keys and normal caller state.
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## Choose the procedure
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Identify the user's task and the service's current state. Read the matching file before acting. Load another only when the task crosses into its scope; an existing service does not need onboarding again.
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
| Task | Read |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| Turn an idea into a working local capability | [new-builder](new-builder.md) |
|
|
19
|
+
| Validate behavior or prove a paid call | [testing](testing.md), then only the chosen payment recipe |
|
|
20
|
+
| Prepare or perform a deployment | [deploying](deploying.md) |
|
|
21
|
+
| Inspect health or earnings, collect payouts, update, or transfer a service | [operating](operating.md) |
|
|
22
|
+
| Diagnose a failure or reconcile an uncertain payment or deploy | [recovery](recovery.md) |
|
|
23
|
+
| Stop offering a service and close its outstanding obligations | [retirement](retirement.md) |
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
For Claude Code, install the complete directory globally:
|
|
25
|
+
## Establish the context
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
mkdir -p "$HOME/.claude/skills/build-dvm"
|
|
27
|
-
cp -R "$skill_dir"/. "$HOME/.claude/skills/build-dvm/"
|
|
28
|
-
```
|
|
27
|
+
Reuse the brief, decisions, and authorization already provided. Ask only for missing choices that affect the result, cost, access, or recoverability. An instruction to test locally does not authorize a production deployment or spending production funds.
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
Inspect the installed CLI version and the project's SDK dependency before selecting examples. Use the exact release and matching skill specified by the builder's setup. Do not upgrade an existing project merely to match an example. If versions disagree, establish the intended target before changing dependencies.
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
mkdir -p .agents/skills/build-dvm
|
|
34
|
-
cp -R "$skill_dir"/. .agents/skills/build-dvm/
|
|
35
|
-
```
|
|
36
|
-
<!-- agent-mirror:verbatim end -->
|
|
31
|
+
Before a remote change, confirm the service, organization, and environment from tool output. Names alone can identify the wrong service when an account belongs to several organizations.
|
|
37
32
|
|
|
38
|
-
|
|
33
|
+
## Rules that apply to every procedure
|
|
39
34
|
|
|
40
|
-
|
|
35
|
+
- Keep private keys, recovery words, payment credentials, and secret values out of chat, source, and logs. Use the documented secret-input mechanism. Never infer that a human has backed up recovery material.
|
|
36
|
+
- Keep the service's price separate from the authorized test-spend cap. Verify the network and payment destination before moving value. A development server can still accept real funds.
|
|
37
|
+
- When an outcome is uncertain, inspect the existing operation before retrying. A lost response does not prove that a payment or deployment failed. Continue through [recovery](recovery.md) when the tool cannot establish the result.
|
|
38
|
+
- Preserve recovery records until the relevant obligation is resolved. Unknown refund state is not a zero balance, and deleting a service does not settle its debts. Use [retirement](retirement.md) before destructive cleanup.
|
|
39
|
+
- Check user authorization before actions that spend funds, change payment destinations, transfer control, or destroy data. Existing authorization counts; do not ask for it again. Ask when the actual scope or consequence exceeds it.
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
## Use the result
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
Read structured output and follow its recovery guidance. Relay `display` and `hint` when they answer the user's question. Check each command's contract: logs and exports need not be JSON.
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
Close a task with the observed result and the evidence relevant to it: a local artifact, a verified paid job, a live deployment, or a confirmed payout. Distinguish completed work from pending or unknown state. Never report a payout from a revenue total alone.
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
Name:
|
|
50
|
-
Capability:
|
|
51
|
-
Input: example JSON and validation rules
|
|
52
|
-
Result: text or named artifact
|
|
53
|
-
Price: $0.01 (or free)
|
|
54
|
-
Paid-test cap: separately approved before test money is spent
|
|
55
|
-
Example: input → result
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
The approved DVM price and the approved paid-test cap are different decisions. A $0.01 DVM can use a $0.02 per-test cap to allow whole-satoshi rounding, but ask for that cap if it is not already approved. Never raise a cap automatically. Do not choose a payment rail or cloud configuration during this interview. A local Cashu mint is test infrastructure, not the builder's production payment choice.
|
|
59
|
-
|
|
60
|
-
## 3. Implement and test the free path
|
|
61
|
-
|
|
62
|
-
Scaffold when it helps; a hand-written Node 22 project with `@dvmkit/sdk` is equally supported.
|
|
63
|
-
|
|
64
|
-
For a hand-written project, pin the admitted SDK exactly:
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
npm install --save-exact @dvmkit/sdk@0.2.1-rc.9
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
dvmctl create my-dvm
|
|
72
|
-
cd my-dvm
|
|
73
|
-
npm install
|
|
74
|
-
npm test
|
|
75
|
-
dvmctl validate
|
|
76
|
-
dvmctl doctor
|
|
77
|
-
dvmctl dev handler.ts
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Keep `handler.ts` small: use `configureDVM`, a Zod `input` schema, a USD `price` string when paid, and `ctx.complete()` with a useful summary. Put provider keys in `.env`, never source code. Add a unit test using `createTestContext` before calling external services. Use the `/_dev` URL printed by `dvmctl dev` to show the builder the free result.
|
|
81
|
-
|
|
82
|
-
Read [the SDK reference](references/sdk-reference.md) for descriptor shapes, job-context methods, streaming, dynamic quotes, auth, persistence, custom routes, and deployment. `dvmctl validate` loads the real handler and checks its capability, schema, example, price, and tags. The `dev` banner states whether payments are skipped or really verified and prints the first caller command.
|
|
83
|
-
|
|
84
|
-
## 4. Exercise a paid local call with test money
|
|
85
|
-
|
|
86
|
-
Use the rail and cap in the approved brief. If either is missing, ask before moving value. Testnet and FakeWallet funds still need the separate cap; production funds always need separate approval. Follow the complete recipe for [Cashu](references/local-cashu-test.md), [x402 on Base Sepolia](references/local-x402-test.md), or [Tempo Moderato](references/local-tempo-test.md). Every recipe isolates `DVM_CONFIG_DIR`, runs `dvmctl dev` without Postgres, proves the advertised test rail and unpaid 402, makes one capped paid call with closed stdin, and verifies the stored receipt. Never label a mainnet rail as test money because the server is in dev mode.
|
|
87
|
-
|
|
88
|
-
## 5. Decide before deployment
|
|
89
|
-
|
|
90
|
-
After the local result and paid test work, show the approved brief, test result, and the exact files changed. Ask whether to prepare deployment. Only then follow the invitation's account and deployment instructions. Production rails, payout configuration, wallet connections, and real funds are separate decisions.
|
|
91
|
-
|
|
92
|
-
Run `dvmctl deploy --dry-run` before a real deploy; Docker is required for a container dry-run. A first real deploy needs a builder signing identity. In a noninteractive run, use `dvmctl deploy --create-identity`; in a terminal, `dvmctl deploy` offers to create the missing identity. Neither route prints the signing secret.
|
|
93
|
-
|
|
94
|
-
Cashu accumulator operation also needs the separate recovery mnemonic created by `dvmctl lock create --human`. That command prints 12 recovery words only in human mode. Pause while the builder writes them down and require their explicit confirmation before continuing. Never infer that the backup happened, capture the words in a log, or replace an existing mnemonic without the builder's explicit instruction.
|
|
95
|
-
|
|
96
|
-
## Reference routing
|
|
97
|
-
|
|
98
|
-
- [Configure and job context](references/configure-context.md): descriptor shapes, context methods, artifacts, cancellation, and costs.
|
|
99
|
-
- [Pricing and credit](references/pricing-credit.md): fiat pricing, quotes, and prepaid credit.
|
|
100
|
-
- [Patterns and auth](references/patterns-auth.md): multi-turn handlers, signed requests, refunds, receipts, and custom routes.
|
|
101
|
-
- [Testing](references/testing.md): schemas, unit contexts, and live-provider boundaries.
|
|
102
|
-
- [Running and deployment](references/running-deployment.md): dev server, host options, persistence, environment, and deployment.
|
|
103
|
-
- [Operating and feedback](references/operating-feedback.md): deployed-DVM operations, revenue, and caller feedback.
|
|
104
|
-
- [Local Cashu paid test](references/local-cashu-test.md): FakeWallet or approved hosted-mint recipe.
|
|
105
|
-
- [Local x402 paid test](references/local-x402-test.md): Base Sepolia USDC recipe.
|
|
106
|
-
- [Local Tempo paid test](references/local-tempo-test.md): Moderato pathUSD recipe.
|
|
107
|
-
- [Payment rails](references/payment-rails.md): test boundaries and production separation.
|
|
47
|
+
For exact syntax and output, read the [dvmctl reference](https://dvmkit.com/docs/cli-dvmctl.md). For handler interfaces, read the [SDK reference](https://dvmkit.com/docs/sdk.md). Use the [docs index](https://dvmkit.com/llms.txt) to retrieve other topics selectively.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Deploy or update a DVM
|
|
2
|
+
|
|
3
|
+
Use this for first deployment and later revisions. Reuse existing authorization; ask only when the target, costs, funds, or destructive effects exceed it.
|
|
4
|
+
|
|
5
|
+
## Establish the target
|
|
6
|
+
|
|
7
|
+
Inspect the project's SDK version, handler, build inputs, and deployment configuration. Read the [hosting explanation](https://dvmkit.com/docs/deploying.md) and the [deploy command contract](https://dvmkit.com/docs/cli-dvmctl.md#deploy) for the chosen target.
|
|
8
|
+
|
|
9
|
+
For Cloud, run `dvmctl auth --status`, `dvmctl orgs`, and `dvmctl whoami`. Select the intended organization with `dvmctl switch` only when needed. If login is missing, follow [authentication](https://dvmkit.com/docs/cli-auth.md); the human completes browser consent. Never create or switch an account merely to get past an access refusal.
|
|
10
|
+
|
|
11
|
+
For an update, record the existing deployment and inspect outstanding jobs and payment obligations. Preserve their database and keys across the update. Establish the effective resources and costs from the current plan; do not promise an unverified spending cap.
|
|
12
|
+
|
|
13
|
+
## Prepare keys and payment operations
|
|
14
|
+
|
|
15
|
+
A real deployment needs a builder signing identity. Inspect it with `dvmctl identity show`; create one only if absent and authorized. `dvmctl deploy --create-identity` can create the missing identity noninteractively. Never replace an existing identity to bypass an error.
|
|
16
|
+
|
|
17
|
+
If accepting Cashu, establish the lock identity and recovery backup. When creation is needed, have the human run `dvmctl lock create --human` in a private terminal and save the recovery words. Do not capture the words in agent output. Require explicit confirmation that the backup is complete before accepting production funds.
|
|
18
|
+
|
|
19
|
+
Read [payments and payouts](https://dvmkit.com/docs/builder-payments.md) and the SDK's [payment environment](https://dvmkit.com/docs/sdk.md#payment-rail-environment-variables) only for the chosen methods. Verify the production network or mints, recipient, and required worker:
|
|
20
|
+
|
|
21
|
+
- Cashu needs the recovery keys, payout destination, and refund/payout worker.
|
|
22
|
+
- Lightning credit needs durable credit storage and a receive-only `DVMKIT_NWC_RECEIVE_URI`. Prepare the separate refund worker; the DVM's receiving connection must not spend.
|
|
23
|
+
- Stablecoin channels need settlement and close handling. Self-hosted Tempo sessions need the documented close observer.
|
|
24
|
+
- One-payment stablecoin credit needs the explicit opt-in and manual refund process before it is offered.
|
|
25
|
+
|
|
26
|
+
## Preview and submit
|
|
27
|
+
|
|
28
|
+
Run project checks, `dvmctl validate`, and `dvmctl doctor`. Preview with `dvmctl deploy --dry-run`; a container preview requires Docker. Resolve failures before a real submission. Do not bypass a dirty-source refusal without an explicit reason and authorization for the exact source being deployed.
|
|
29
|
+
|
|
30
|
+
For Cloud, supply secret values through a secret manager into `dvmctl deploy --env-stdin` as the documented JSON string map. This option is Cloud-only and is not accepted by dry-run. Do not put secrets in command arguments, source, or logs. Inspect `.env` as an input boundary without printing its values: Cloud deployment reads it too.
|
|
31
|
+
|
|
32
|
+
Submit the authorized deployment once and retain its deployment ID. For an ambiguous response, inspect `dvmctl deploy-status <id>` and the service before retrying; use [recovery](recovery.md) when the result remains unknown.
|
|
33
|
+
|
|
34
|
+
For self-hosting, initialize the durable service ID with `dvmctl init <slug> --self-hosted`, then run `dvmctl deploy --target self-host`. Protect any generated attestation and receipt-key values as secrets. Deploy the generated container with the target's tools, configure its durable database and secrets, and operate the required payment workers yourself. Generating these files is not a completed deployment.
|
|
35
|
+
|
|
36
|
+
## Verify the deployed service
|
|
37
|
+
|
|
38
|
+
Inspect the actual endpoint, active revision, and health. Read `/v1/info` or `dvm describe` to confirm capability, price, signing identity, and intended payment configuration. Test the agreed example and retrieve its output.
|
|
39
|
+
|
|
40
|
+
For a production paid acceptance, follow [testing](testing.md) with the already approved funds and cap. If that scope is absent, report the deployment evidence and the specific paid check still unperformed. Never claim receipt or payout from a successful build alone.
|
|
41
|
+
|
|
42
|
+
Record the endpoint, deployed revision, validation result, and any pending payment operation. Continue to [operating](operating.md) for earnings and payout work.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Build a first capability
|
|
2
|
+
|
|
3
|
+
Use this for a new service or a new capability. For an existing service, inspect its handler, dependencies, and conventions before changing it. Do not scaffold over a populated directory.
|
|
4
|
+
|
|
5
|
+
## Establish one example
|
|
6
|
+
|
|
7
|
+
Reuse the supplied brief. Ask only for missing decisions that affect the result: capability name, typed input, expected output, one input-to-result example, and price. Establish external provider costs if the handler will call a paid API. Keep the paid-test cap separate from the service price.
|
|
8
|
+
|
|
9
|
+
Start with one capability unless the brief needs more. Record the agreed example in the project so validation and the final report use the same expectation. Defer production payment and hosting choices until they are needed by the authorized task.
|
|
10
|
+
|
|
11
|
+
## Implement the handler
|
|
12
|
+
|
|
13
|
+
For a new scaffold:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
dvmctl create my-dvm
|
|
17
|
+
cd my-dvm
|
|
18
|
+
npm install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Use the scaffold's pinned SDK. For a handwritten project, pin the SDK version admitted by the installed CLI and skill. Read only the relevant parts of the [SDK reference](https://dvmkit.com/docs/sdk.md): [descriptor](https://dvmkit.com/docs/sdk.md#configuredvm), [input](https://dvmkit.com/docs/sdk.md#input-validation-with-zod), and [job context](https://dvmkit.com/docs/sdk.md#the-job-context).
|
|
22
|
+
|
|
23
|
+
Implement the agreed input and result. Validate input with the SDK's exported Zod instance. Use the SDK's completion and artifact APIs so callers can retrieve and verify the result. For dynamic pricing, storage, or external side effects, load the corresponding SDK section before selecting an interface.
|
|
24
|
+
|
|
25
|
+
Keep provider credentials outside committed source. Test the handler's behavior with `createTestContext` before spending on a provider. Mock the external dependency for handler tests, then use a separately authorized live check to prove the provider accepts the actual request shape. A mocked response does not establish that contract.
|
|
26
|
+
|
|
27
|
+
## Prove the local result
|
|
28
|
+
|
|
29
|
+
Run the project's tests and typecheck, then:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
dvmctl validate
|
|
33
|
+
dvmctl doctor
|
|
34
|
+
dvmctl dev handler.ts
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Read the dev banner before calling it. Payment verification is skipped only when no rail is configured; a configured rail can move real value. Use the printed `/_dev` interface or caller command to run the agreed example. Use `/_dev` when the caller CLI is not installed; the paid-test recipes install their own isolated caller. For an object input, the HTTP request uses `data`; the caller CLI uses `--data`.
|
|
38
|
+
|
|
39
|
+
Retrieve the terminal result and any advertised artifacts. Compare their contents with the agreed example, not only the command's exit status. If the handler fails, fix it before adding payment complexity.
|
|
40
|
+
|
|
41
|
+
Report the implemented capability, observed result, and artifact location. Continue to [testing](testing.md) for paid evidence or to [deploying](deploying.md) when those tasks are already authorized.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Operate an existing service
|
|
2
|
+
|
|
3
|
+
Resolve the requested service and organization with `dvmctl list`, `dvmctl info <slug>`, and `dvmctl whoami`. Confirm them from output before a remote change. Read the [dvmctl reference](https://dvmkit.com/docs/cli-dvmctl.md) for exact flags and output; do not load every operation below.
|
|
4
|
+
|
|
5
|
+
## Inspect health
|
|
6
|
+
|
|
7
|
+
Use `status` for compute state, `metrics` for the relevant time window, and `events` or `logs` for the incident. Logs can be raw text. Correlate the job and deployment IDs before acting on an error from an older revision.
|
|
8
|
+
|
|
9
|
+
A running process does not prove the handler or payment path works. Verify an appropriate capability call after a repair. Route an uncertain job, deploy, or payment outcome to [recovery](recovery.md).
|
|
10
|
+
|
|
11
|
+
## Inspect earnings and collect payouts
|
|
12
|
+
|
|
13
|
+
Use `dvmctl revenue summary` for totals and `revenue events` or `revenue csv` for the requested period and organization. Report these as earnings, not a wallet balance.
|
|
14
|
+
|
|
15
|
+
For Cashu, confirm the intended Lightning payout destination with the service configuration. Set or change it only within authorization using `dvmctl set-payout`. Run `dvmctl melt-pending <slug>` for a pass or its documented watch mode for continued service, then inspect `dvmctl melt-status` and the destination's receipt evidence.
|
|
16
|
+
|
|
17
|
+
Keep the refund and payout roles separate. The worker can use `DVMKIT_REFUND_NWC_URL` to buy ecash for caller refunds and `DVMKIT_MELT_PAYOUT_NWC_URL` to receive builder payouts. Supply these through its secret environment. The DVM's `DVMKIT_NWC_RECEIVE_URI` only receives Lightning credit payments. Never reuse a send-capable connection as that receiving credential.
|
|
18
|
+
|
|
19
|
+
If caller refunds remain or drain state cannot be read, preserve the payout hold and use [recovery](recovery.md). Do not treat an unavailable liability query as a zero balance.
|
|
20
|
+
|
|
21
|
+
For stablecoins, verify the configured network and recipient, then inspect the transfer or channel settlement evidence. Keep required close observers running. For opted-in one-payment credit refunds, inspect `dvmctl credit drains-owed`, perform only the authorized transfer, and record the real transaction with `credit drain-settle`. Never record a payment merely to clear the queue.
|
|
22
|
+
|
|
23
|
+
## Change the service
|
|
24
|
+
|
|
25
|
+
Choose the command matching the requested change. Use [deploying](deploying.md) for a new revision. Use restart, scale, environment, domain, or database commands only after checking their target and consequences in the reference. A machine restart does not repair a missing payment record.
|
|
26
|
+
|
|
27
|
+
Before a transfer, inspect the current owner, intended destination organization, and custody consequences. After transfer, verify the resulting owner and any pending treasury re-key. Follow the required redeployment before reporting payouts ready.
|
|
28
|
+
|
|
29
|
+
For temporary suspension, use the documented pause/resume path and verify availability afterward. For permanent removal or data deletion, read [retirement](retirement.md) first.
|
|
30
|
+
|
|
31
|
+
Close with the observed state, change made, and remaining action. Report a payout only when transfer evidence supports it; keep earnings, pending settlement, and funds delivered distinct.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Recover an uncertain or failed operation
|
|
2
|
+
|
|
3
|
+
Start from the operation that failed, not from onboarding. Preserve its service, organization, endpoint, job/deployment/funding IDs, time window, caller journal, and receipt. Keep secrets out of the report.
|
|
4
|
+
|
|
5
|
+
## Determine whether it happened
|
|
6
|
+
|
|
7
|
+
Read the command's structured error and recovery hint. Distinguish a refusal before submission from a pending operation or lost response. Stop dependent money movement while the result is unknown.
|
|
8
|
+
|
|
9
|
+
| Operation | First evidence |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Deployment | Existing deployment status, active service revision, and events |
|
|
12
|
+
| Job or paid submit | Original caller profile, request ID, job state, messages, and receipt |
|
|
13
|
+
| Lightning credit funding | Original fund ID, invoice settlement evidence, and a credit balance read |
|
|
14
|
+
| Cashu payout or refund | Melt status, pending drains, retained proofs, and wallet or mint evidence |
|
|
15
|
+
| Stablecoin settlement | Correct network's transaction receipt and channel state |
|
|
16
|
+
|
|
17
|
+
Do not create a new funding, request, or deployment merely because the prior response was lost. Use the original operation's supported resume/reconcile path. A fresh request ID changes the operation; it is not a retry.
|
|
18
|
+
|
|
19
|
+
For Lightning funding, `dvm credit balance <endpoint>` can prompt recognition of the paid invoice. Keep the receiving wallet reachable. If confirmation is blocked, use the builder's blocked-invoice inspection below; do not pay another invoice to compensate for an unknown one.
|
|
20
|
+
|
|
21
|
+
## Choose a supported repair
|
|
22
|
+
|
|
23
|
+
Read only the relevant [dvmctl command contract](https://dvmkit.com/docs/cli-dvmctl.md) before invoking a repair:
|
|
24
|
+
|
|
25
|
+
- `credit blocked` inspects Lightning invoice problems; `credit reconcile` checks the existing payment evidence.
|
|
26
|
+
- `credit x402-wedged` and `credit x402-reconcile` inspect and reconcile x402 settlement.
|
|
27
|
+
- `credit tempo-wedged` and `credit tempo-reconcile` inspect and reconcile Tempo drains.
|
|
28
|
+
- `credit drains-owed` identifies manual stablecoin refunds. `credit drain-settle` records a transfer that actually happened; it does not send the funds.
|
|
29
|
+
- `melt-pending` services ecash refunds before builder payout. Restore missing worker credentials or connectivity without removing the refund hold.
|
|
30
|
+
|
|
31
|
+
A write-off accepts loss or abandons recovery. Explain the exact obligation and consequence and require authorization for that loss before using a write-off command. Do not substitute write-off for a reconciliation that has not established the outcome.
|
|
32
|
+
|
|
33
|
+
For runtime failure, inspect current logs, configuration names, dependencies, and persistence before restarting or rolling back. A rollback does not undo external transfers or necessarily restore an earlier database schema. Never rotate or delete recovery keys as a general repair. If a rotation reached the DVM but its platform update is pending, follow the CLI's synchronization hint; rotating again would create another key change.
|
|
34
|
+
|
|
35
|
+
## Verify and retain evidence
|
|
36
|
+
|
|
37
|
+
Re-read the original operation and its liability or balance after the repair. Verify the actual job result or funds movement as relevant. A repair command exiting successfully is not sufficient if the underlying state is still pending.
|
|
38
|
+
|
|
39
|
+
Retain records until all dependent obligations resolve. If evidence is unavailable, report the precise unknown state and the dependency needed to resolve it. Do not claim zero liability or destroy the service to make an unresolved queue disappear. Permanent shutdown belongs in [retirement](retirement.md).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Lightning-funded credit acceptance
|
|
2
|
+
|
|
3
|
+
Use this only with an authorized Lightning funding amount and a durable service. Lightning funds prepaid credit; it is not a per-job payment rail. Ordinary `dvmctl dev` has disposable state and does not provide this test boundary. There is no public FakeWallet NWC recipe to substitute here.
|
|
4
|
+
|
|
5
|
+
## Establish the service and wallets
|
|
6
|
+
|
|
7
|
+
Verify the service has descriptor-level auth, enabled credit, durable Postgres storage, and a receive-only `DVMKIT_NWC_RECEIVE_URI`. Confirm Lightning appears in its credit funding menu. Read the advertised minimum before choosing the deposit; a per-job cap does not authorize raising the deposit to meet that minimum.
|
|
8
|
+
|
|
9
|
+
Use a separately approved caller wallet and funding amount. Supply its NWC connection through a secret store into stdin for `dvm wallet connect`, never as an argument or chat message. The caller's connection pays invoices; the service's receiving connection must not.
|
|
10
|
+
|
|
11
|
+
Create an isolated `DVM_CONFIG_DIR`, initialize `dvm`, and connect only that test wallet. Read the [caller wallet reference](https://dvmkit.com/docs/dvm-cli.md) for connection and policy options. A declared CLI budget does not impose a wallet-side per-payment routing-fee cap. Keep the caller state until all credit and payment outcomes are resolved.
|
|
12
|
+
|
|
13
|
+
## Fund once, then spend credit
|
|
14
|
+
|
|
15
|
+
Set the endpoint, deposit, input, and job cap from the existing authorization. Record the caller's wallet balance and transaction-history checkpoint without logging credentials.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
dvm credit fund "$DVM_ENDPOINT" --amount "$DVM_CREDIT_DEPOSIT" --rail lightning
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Retain the returned credit and funding IDs. Confirm the exact invoice payment in the caller wallet's own history and the builder wallet's paid-invoice lookup. Match these with the DVM's signed funding record and confirmed credit balance. Reconcile principal, fees, and the observed wallet debit. CLI success alone is not independent settlement evidence.
|
|
22
|
+
|
|
23
|
+
If the response is pending or lost, keep the original journal and use `dvm credit balance "$DVM_ENDPOINT"` to check recognition. Never create another funding to bypass uncertainty. A later balance read, poll, or job submit causes the service to recognize settlement; there is no background invoice watcher.
|
|
24
|
+
|
|
25
|
+
Select the returned credit with `dvm credit balance "$DVM_ENDPOINT" --credit-id "$DVM_CREDIT_ID"`. After that balance is confirmed, make one draw from it with a stable request ID:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
dvm request --endpoint "$DVM_ENDPOINT" --data "$DVM_INPUT" --budget "$DVM_JOB_CAP" --credit-only "$DVM_CREDIT_ID" --request-id "$DVM_REQUEST_ID" </dev/null
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`--credit-only` forbids fallback to a fresh payment. Retain the request ID for recovery. Retrieve the job's messages and artifacts, verify the expected result, and run `dvm receipts verify <job-id>`. Compare the before/after credit balance with the settled draw and check that no second Lightning payment occurred.
|
|
32
|
+
|
|
33
|
+
## Close the test's obligations
|
|
34
|
+
|
|
35
|
+
Unused credit is still owed to the caller. Follow the caller's documented drain procedure within authorization and operate the builder refund worker. Lightning-funded credit returns as ecash. The worker may need separately authorized spending access to mint that ecash; it does not send a reverse Lightning refund.
|
|
36
|
+
|
|
37
|
+
Report the funded amount, job charge, fees, remaining credit, and refund status separately. Retain unresolved journals and recovery state. Do not delete the isolated caller profile merely because the job completed.
|
|
@@ -22,7 +22,11 @@ cleanup() {
|
|
|
22
22
|
trap - EXIT INT TERM
|
|
23
23
|
[ -z "$dvm_pid" ] || kill "$dvm_pid" 2>/dev/null || true
|
|
24
24
|
[ -z "$mint_id" ] || docker rm -f "$mint_id" >/dev/null 2>&1 || true
|
|
25
|
-
|
|
25
|
+
if [ "$status" -eq 0 ]; then
|
|
26
|
+
rm -rf "$test_root"
|
|
27
|
+
else
|
|
28
|
+
printf "Test failed; recovery state retained at %s\n" "$test_root" >&2
|
|
29
|
+
fi
|
|
26
30
|
exit "$status"
|
|
27
31
|
}
|
|
28
32
|
trap cleanup EXIT
|
|
@@ -73,7 +77,8 @@ if (response.status !== 402 || body.error !== "payment_required" || !Number.isSa
|
|
|
73
77
|
writeFileSync(output, JSON.stringify(body));
|
|
74
78
|
NODE
|
|
75
79
|
|
|
76
|
-
npm install -
|
|
80
|
+
npm install --ignore-scripts --prefix "$test_root/tools" @dvmkit/dvm-cli@0.3.0
|
|
81
|
+
export PATH="$test_root/tools/node_modules/.bin:$PATH"
|
|
77
82
|
dvm init
|
|
78
83
|
dvm wallet init
|
|
79
84
|
dvm wallet mint-add "$cashu_mint_url"
|
|
@@ -12,7 +12,17 @@ test_root="$(mktemp -d "${TMPDIR:-/tmp}/dvmkit-tempo-paid.XXXXXX")"
|
|
|
12
12
|
export DVM_CONFIG_DIR="$test_root/caller"
|
|
13
13
|
mkdir -p "$DVM_CONFIG_DIR"
|
|
14
14
|
dvm_pid=""
|
|
15
|
-
cleanup() {
|
|
15
|
+
cleanup() {
|
|
16
|
+
status=$?
|
|
17
|
+
trap - EXIT INT TERM
|
|
18
|
+
[ -z "$dvm_pid" ] || kill "$dvm_pid" 2>/dev/null || true
|
|
19
|
+
if [ "$status" -eq 0 ]; then
|
|
20
|
+
rm -rf "$test_root"
|
|
21
|
+
else
|
|
22
|
+
printf "Test failed; recovery state retained at %s\n" "$test_root" >&2
|
|
23
|
+
fi
|
|
24
|
+
exit "$status"
|
|
25
|
+
}
|
|
16
26
|
trap cleanup EXIT
|
|
17
27
|
trap 'exit 130' INT TERM
|
|
18
28
|
|
|
@@ -47,7 +57,8 @@ if(response.status!==402 || body.error!=="payment_required" || !Number.isSafeInt
|
|
|
47
57
|
writeFileSync(output,JSON.stringify(body));
|
|
48
58
|
NODE
|
|
49
59
|
|
|
50
|
-
npm install -
|
|
60
|
+
npm install --ignore-scripts --prefix "$test_root/tools" @dvmkit/dvm-cli@0.3.0
|
|
61
|
+
export PATH="$test_root/tools/node_modules/.bin:$PATH"
|
|
51
62
|
dvm init
|
|
52
63
|
dvm wallet tempo-connect --network moderato
|
|
53
64
|
dvm wallet fund '$1' --rail tempo
|
|
@@ -13,7 +13,17 @@ test_root="$(mktemp -d "${TMPDIR:-/tmp}/dvmkit-x402-paid.XXXXXX")"
|
|
|
13
13
|
export DVM_CONFIG_DIR="$test_root/caller"
|
|
14
14
|
mkdir -p "$DVM_CONFIG_DIR"
|
|
15
15
|
dvm_pid=""
|
|
16
|
-
cleanup() {
|
|
16
|
+
cleanup() {
|
|
17
|
+
status=$?
|
|
18
|
+
trap - EXIT INT TERM
|
|
19
|
+
[ -z "$dvm_pid" ] || kill "$dvm_pid" 2>/dev/null || true
|
|
20
|
+
if [ "$status" -eq 0 ]; then
|
|
21
|
+
rm -rf "$test_root"
|
|
22
|
+
else
|
|
23
|
+
printf "Test failed; recovery state retained at %s\n" "$test_root" >&2
|
|
24
|
+
fi
|
|
25
|
+
exit "$status"
|
|
26
|
+
}
|
|
17
27
|
trap cleanup EXIT
|
|
18
28
|
trap 'exit 130' INT TERM
|
|
19
29
|
|
|
@@ -50,7 +60,8 @@ if(response.status!==402 || body.error!=="payment_required" || !Number.isSafeInt
|
|
|
50
60
|
writeFileSync(output,JSON.stringify(body));
|
|
51
61
|
NODE
|
|
52
62
|
|
|
53
|
-
npm install -
|
|
63
|
+
npm install --ignore-scripts --prefix "$test_root/tools" @dvmkit/dvm-cli@0.3.0
|
|
64
|
+
export PATH="$test_root/tools/node_modules/.bin:$PATH"
|
|
54
65
|
dvm init
|
|
55
66
|
dvm wallet x402-connect --key-file "$X402_TESTNET_KEY_FILE" --network "eip155:84532"
|
|
56
67
|
dvm wallet balance >"$test_root/balance.json"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Retire a service
|
|
2
|
+
|
|
3
|
+
Use this only when the user intends to stop offering the service or remove its infrastructure. For an incident or uncertain payment, use [recovery](recovery.md).
|
|
4
|
+
|
|
5
|
+
## Establish the shutdown scope
|
|
6
|
+
|
|
7
|
+
Confirm the service, organization, and endpoint from current output. Distinguish a temporary pause from permanent removal, including whether the database should remain. Existing authorization counts, but an instruction to stop compute does not imply permission to delete financial records.
|
|
8
|
+
|
|
9
|
+
Read the [destroy and pause contracts](https://dvmkit.com/docs/cli-dvmctl.md) before changing availability. Pause stops routing and compute while preserving service resources. It also makes the service unavailable to callers, so it is not a way to keep serving refunds.
|
|
10
|
+
|
|
11
|
+
## Account for obligations
|
|
12
|
+
|
|
13
|
+
Inspect active jobs, open caller credit, pending drains, unsettled channels, pending ecash, and payout state. Use the operational and credit inspection commands for the configured methods. Reconcile unavailable or inconsistent evidence before treating anything as empty.
|
|
14
|
+
|
|
15
|
+
Preserve the database, signing identity, Cashu recovery material, and caller-refund records needed to complete outstanding work. Keep the receiving wallet and settlement/refund workers available for obligations that still depend on them. Lightning payments already received can still back unused caller credit.
|
|
16
|
+
|
|
17
|
+
Resolve refunds and settlements through their normal paths and verify delivery. Do not send an unrelated manual transfer for a channel-backed refund or record a transfer that has not occurred. Route stuck states to [recovery](recovery.md).
|
|
18
|
+
|
|
19
|
+
## Remove only the authorized resources
|
|
20
|
+
|
|
21
|
+
Use the platform's wind-down behavior when destruction reports outstanding credit. Inspect the returned state and continue serving the outstanding obligations; a `winding_down` response is not completed removal.
|
|
22
|
+
|
|
23
|
+
When permanent destruction is authorized and its consequences are understood, invoke `dvmctl destroy <slug> --confirm`, adding `--keep-db` when retaining the database is part of the shutdown plan. The default can remove the paired database. Never choose the default while that database is still needed for recovery.
|
|
24
|
+
|
|
25
|
+
For self-hosted services, remove infrastructure through the host's tools only after the same obligation check. Cloud commands do not destroy the separately managed host.
|
|
26
|
+
|
|
27
|
+
## Confirm the final state
|
|
28
|
+
|
|
29
|
+
Verify service availability, platform state, remaining infrastructure, and unresolved balances. Preserve necessary financial evidence before revoking the credentials required to inspect it. Revoke obsolete platform and wallet access deliberately; destroying compute does not revoke external connections.
|
|
30
|
+
|
|
31
|
+
Report what stopped, what was removed, what remains retained or payable, and who must act next. Call retirement complete only when the agreed resources and obligations are accounted for.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Test a capability and its payment path
|
|
2
|
+
|
|
3
|
+
Select the evidence the change needs. Handler tests establish behavior; live provider checks establish an external request contract; a paid call establishes the selected payment path. Do not substitute one for another.
|
|
4
|
+
|
|
5
|
+
## Before moving value
|
|
6
|
+
|
|
7
|
+
1. Read the approved price, test rail, and spend cap. A per-call cap does not authorize an arbitrary wallet deposit. Establish any funding amount and provider spend separately if not already approved.
|
|
8
|
+
2. Verify the endpoint, advertised capability, network or mint, and payment destination. Read the dev banner. Local execution does not imply fake funds.
|
|
9
|
+
3. Isolate the test caller with a fresh `DVM_CONFIG_DIR`. Keep it separate from the builder's recovery material and normal caller wallet. Use the admitted caller CLI version.
|
|
10
|
+
4. Run `dvmctl validate`, `dvmctl doctor`, and the project's checks. For a paid upstream API, verify the request shape against the live provider within the authorized spend before selling the capability.
|
|
11
|
+
|
|
12
|
+
## Select one payment recipe
|
|
13
|
+
|
|
14
|
+
Load only the recipe needed for the approved test:
|
|
15
|
+
|
|
16
|
+
| Payment path | Procedure | Boundary |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| Cashu per-job | [Cashu test](references/local-cashu-test.md) | Owned or approved hosted FakeWallet mint |
|
|
19
|
+
| x402 per-job | [x402 test](references/local-x402-test.md) | Base Sepolia test USDC |
|
|
20
|
+
| Tempo per-job | [Tempo test](references/local-tempo-test.md) | Moderato test currency |
|
|
21
|
+
| Lightning-funded credit | [Lightning acceptance](references/lightning-credit-test.md) | Durable service and separately approved wallet-backed funds |
|
|
22
|
+
|
|
23
|
+
The three local per-job recipes use disposable dev state without Postgres. Lightning funds prepaid credit and needs durable storage; do not invent a per-job Lightning test or substitute a production wallet into a fake-money recipe.
|
|
24
|
+
|
|
25
|
+
Apply the actual approved input and caps to the recipe before running it. Read its prerequisites and cleanup behavior first. Do not automatically increase a cap or change a network to make a refusal disappear.
|
|
26
|
+
|
|
27
|
+
## Assess the result
|
|
28
|
+
|
|
29
|
+
Require a terminal job, the expected content, all advertised artifacts, and a verified stored receipt. Verify the rail and amount against the unpaid quote or the selected credit draw. Require independent wallet or chain evidence for the original payment. Receipt verification alone does not establish where value arrived.
|
|
30
|
+
|
|
31
|
+
A successful test establishes only that endpoint, revision, rail, and network. State those limits in the result. Keep nonsecret evidence needed to reproduce the finding.
|
|
32
|
+
|
|
33
|
+
On a pending or lost response, keep the caller profile and operation identifiers and continue through [recovery](recovery.md). Cleanup is allowed only after outcomes are known and remaining value is recovered or explicitly disposable. A pending payment journal is recovery material, not a temporary file to delete.
|