@c4roa0/agentpay-user 0.3.1 → 0.3.3

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/AGENTS.md CHANGED
@@ -135,3 +135,13 @@ load Protocol fixtures from the pinned public package, not a source checkout.
135
135
  Do not remove scripts merely because their name contains smoke or Anvil: some are
136
136
  current onboarding entries. Review callers first. Never weaken signer or payment
137
137
  boundaries to simplify tests. Keep source maps and behavioral evidence limits current.
138
+
139
+ ## Tag-triggered npm releases
140
+
141
+ Package version `X.Y.Z` is released by pushing tag `vX.Y.Z` at the exact reviewed
142
+ source commit. `.github/workflows/publish.yml` validates this match, verifies the
143
+ package, publishes through OIDC and checks registry integrity. Pushing a release
144
+ tag is a publication action and needs maintainer authorization; ordinary branch
145
+ pushes do not publish. Never move an existing release tag. Verify registry state
146
+ before rerunning a failed publication. The `npm-publish` environment must allow
147
+ release tags (for example `v*`), not only the main branch.
package/README.md CHANGED
@@ -15,7 +15,7 @@ Install User with the command below. It automatically installs the matching Wall
15
15
  and Protocol packages; you do not need to download two repositories:
16
16
 
17
17
  ```sh
18
- npm install --global @c4roa0/agentpay-user@0.3.1
18
+ npm install --global @c4roa0/agentpay-user
19
19
  agentpay install --market https://YOUR_MARKET_ORIGIN
20
20
  ```
21
21
 
@@ -33,6 +33,24 @@ normally live in `~/.local/share/agentpay/user`; an existing custom data directo
33
33
  is retained. Installation checkpoints use `~/.local/state/agentpay/user` (or
34
34
  `$XDG_STATE_HOME/agentpay/user`). Upgrading program files does not erase either.
35
35
 
36
+ ## Install in a folder instead
37
+
38
+ For a directory-owned installation, choose a program folder:
39
+
40
+ ```sh
41
+ mkdir agentpay-local
42
+ cd agentpay-local
43
+ npm install @c4roa0/agentpay-user
44
+ ./node_modules/.bin/agentpay help
45
+ ```
46
+
47
+ Use `./node_modules/.bin/agentpay` instead of `agentpay` in the commands below.
48
+ `update` updates this installation and its project lockfile; it does not install
49
+ User globally. For an existing Wallet, use `repair` to refresh the background
50
+ services against this installation. Private data stays in its existing directory.
51
+ Before deleting the program folder, run `uninstall` to remove managed services;
52
+ private data is kept unless you explicitly choose `--delete-data`.
53
+
36
54
  ## After setup
37
55
 
38
56
  ```sh
@@ -44,7 +62,7 @@ agentpay market connect
44
62
 
45
63
  Linux background services use your systemd user session. Wallet starts locked after
46
64
  a restart. `agentpay service help` explains startup, stop and logs; `agentpay help` lists
47
- all groups. Global npm installations use `agentpay update` to review and install a
65
+ all groups. npm installations use `agentpay update` to review and install a
48
66
  new User version with its matching Wallet and official test Skill. Source checkouts
49
67
  update their files, run `npm ci`, then `agentpay repair`. [Commands](doc/runbooks/commands.md) · [Updates](doc/runbooks/local-update.md)
50
68
  · [Backup and restore](doc/runbooks/wallet-identity.md).
package/doc/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # User documentation
2
2
 
3
+ - [Directory npm update verification](records/local-npm-update-2026-11-08.md): real package update and preflight boundary.
4
+
3
5
  ## Start by role
4
6
 
5
7
  | Reader | Start here |
package/doc/TODO.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # User TODO
2
2
 
3
+ ## Directory npm update, then HTTPS
4
+
5
+ - [x] Support directory-local npm update without replacing source/link installs.
6
+ - [x] Verify real npm directory upgrade and isolated preflight; nine regression checks passed.
7
+ - [ ] Publish a follow-up version and verify participant directory install/update.
8
+
9
+ ## Tag-triggered publication
10
+
11
+ - [x] Use matching `vX.Y.Z` tags for npm publication; retain verification gates.
12
+ - [x] Owner confirmed release tags allowed in the GitHub `npm-publish` environment.
13
+ - [x] Verify first tag-triggered OIDC run 42491753287 and registry archive integrity.
14
+
15
+ ## Official package 1.2.1 — 2026-11-08
16
+
17
+ - [x] Review actual published bytes, update the built-in official pin and verify fixed-download checks. Real Market fixed-version download/install repeated successfully in an isolated directory.
18
+ - [x] Inspect this participant installation’s prior-version official tests: saved 1.2.0 record is acknowledged; retained unchanged. This does not assert every user has completed old tests.
19
+ - [x] Load the reviewed User source update and run the normal 1.2.1 payment test with explicit user consent; terminal delivery/result/ack completed.
20
+ - [x] Verify website visibility and independently reconcile Settlement/chain outcome; prepare User 0.3.2 candidate.
21
+ - [x] Pin the verified public Wallet 0.3.2; align package/lockfile/update-pair.
22
+ - [x] Publish User 0.3.2 through tag-triggered OIDC; verify public registry archive.
23
+ - [ ] Accept a real participant npm update/restart.
24
+
25
+
26
+ ## Fixed Skill download loop — 2026-11-08
27
+
28
+ - [x] Request the official ZIP by the built-in SHA-256; reject unavailable/substituted versions without fallback.
29
+ - [x] Complete fixed-download regression/type checks and publication/deletion review; the separate Market schema-fixture issue was resolved in its later regression.
30
+ - [ ] After Market API/Web/nginx support is live, publish the next User version (not 0.3.1 again) and verify old pinned ZIP download and participant upgrade.
31
+
32
+
3
33
  ## Running-version release loop — 2026-11-07
4
34
 
5
35
  - [x] Verify User 0.3.0 public-registry publication; Trusted Publisher configured.
@@ -7,7 +37,8 @@
7
37
  - [x] Add process-start software reporting and status/repair mismatch handling; isolated checks passed.
8
38
  - [x] Wallet 0.3.1 published through the configured workflow; public npm version/dependencies verified.
9
39
  - [x] Pin User 0.3.1 to published Wallet 0.3.1; pairing metadata/lockfile and standalone archive verification complete.
10
- - [ ] Publish matching User release; validate User OIDC and real published-version update/restart.
40
+ - [x] Publish User 0.3.1; verify public npm/latest and successful Wallet/User OIDC runs.
41
+ - [ ] Verify real published-version update/restart on the participant installation.
11
42
 
12
43
 
13
44
  ## npm update follow-up — 2026-11-07
@@ -25,11 +56,12 @@
25
56
  - [x] Review step 2: guard normal packing against missing/stale builds, correct public-interface docs and verify a standalone TypeScript consumer.
26
57
  - [x] Step 3: migrate User to Wallet npm dependency and `agentpay` entry; remove sibling/build assumptions; isolated tarball/process acceptance passed.
27
58
  - [x] Step 4a: exact installed-package checks, service-path/client relocation, installer lock, recovery-safe preparation and explicit uninstall modes.
28
- - [ ] Step 4b: running-daemon version/interface negotiation and participant upgrade/interruption acceptance.
59
+ - [x] Step 4b implementation: installed/running version and interface checks.
60
+ - [ ] Step 4b acceptance: participant upgrade/interruption recovery (same gate as the running-version loop above).
29
61
  - [ ] Step 5: publish Wallet then User via OIDC; verify registry installs and update Market guides.
30
62
  - [x] Wallet 0.3.0 first Token publication; registry integrity/latest and fresh public install/CLI/IPC verified.
31
- - [x] Owner configured Wallet npm Trusted Publisher (pending validation).
32
- - [ ] Validate Wallet and User OIDC with later reviewed releases. Both 0.3.0 packages are published; Market guide updates remain pending.
63
+ - [x] Owner configured Wallet npm Trusted Publisher; validated by 0.3.1 publication.
64
+ - [x] Wallet and User OIDC validated by 0.3.1 releases; Market guide updates remain pending.
33
65
  - [ ] Step 6: participant setup/upgrade/restart/uninstall and official Anvil paid acceptance.
34
66
 
35
67
 
@@ -58,7 +90,7 @@
58
90
  ## Independent distribution (next development loop)
59
91
 
60
92
  - [ ] Define the supported Wallet client/IPC boundary and source/build/running compatibility requirements.
61
- - [ ] Replace exact version pairing with reviewed compatibility checks; preserve keys, Policies and recovery.
93
+ - [ ] Optional later: widen exact reviewed dependency pairs only with a verified compatibility matrix; preserve keys, Policies and recovery.
62
94
  - [ ] Optional later: combined ZIP/platform assets after primary npm installation acceptance.
63
95
  - [ ] Verify fresh Git/ZIP installation and missing/incompatible/stale version recovery; update Market guidance.
64
96
 
@@ -30,6 +30,7 @@ name change. Independent-version compatibility remains a separate planned featur
30
30
  | Area | Main files | Responsibility |
31
31
  | --- | --- | --- |
32
32
  | CLI | `run`, `scripts/agentpay-cli.mjs`, `src/user-cli.mjs` | Node discovery, grouped commands and help |
33
+ | npm update | `npm-update.mjs` | Detect global/direct-project installation, isolate npm preflight, pin the reviewed release and repair services without changing private data |
33
34
  | Install / repair | `install-user.mjs`, `install-and-setup.mjs`, `install-preflight.mjs`, `local-update.mjs` | Dependency/build preparation, checkpoints, downloaded settings and safe restart |
34
35
  | Setup | `guided-setup.mjs`, `user-setup-guide.mjs`, `anvil-onboarding.mjs` | Terminal sequence and saved-step continuation; explicit signer mode |
35
36
  | Permission | `policy-terminal-guide.mjs`, `safe-policy-plan.mjs`, `renew-policy.mjs`, `policy-operations.mjs`, `policy-migration.mjs` | Drafts, approved operations and verified local binding |
@@ -0,0 +1,28 @@
1
+ # Directory npm update verification — 2026-11-08
2
+
3
+ The updater accepts a direct registry dependency in a project installation as well
4
+ as a global installation. The owning folder comes from the running package, not
5
+ the terminal working directory. Source/link, custom-source and transitive installs
6
+ remain outside automatic updates. Confirmation, exact release pinning, private-data
7
+ retention and the existing service repair flow remain in effect.
8
+
9
+ Nine controlled regression checks passed, covering global/local update, cancellation,
10
+ forced confirmation, failures, concurrent changes and unsupported install layouts.
11
+ A real-npm check installed public User 0.3.1 into a temporary project, ran the changed
12
+ updater against public 0.3.2 and verified program, manifest and lockfile versions.
13
+ Private-record fixture bytes were preserved. Service stop/repair hooks were controlled;
14
+ this is not participant process recovery or paid acceptance.
15
+
16
+ npm 10.9.8 dry-run changed node_modules/.package-lock.json without replacing program
17
+ files. The subsequent install could report up to date while leaving old code.
18
+ Lock-related flags did not reliably prevent this. Preflight now uses a disposable
19
+ prefix with privately copied project npm settings for consistent registry selection,
20
+ removed afterward. The real check confirms the existing hidden lockfile stays on
21
+ the old version after preflight. No participant keys, services or payments were used.
22
+
23
+ Follow-up publication and participant directory-update acceptance remain pending.
24
+
25
+ User 0.3.3 release preparation (2026-11-09): all 383 behavior checks and standalone
26
+ archive installation with isolated Wallet/Runtime process checks passed. Wallet
27
+ 0.3.2, Protocol 0.14.3 and official package pin are unchanged. Publication and
28
+ participant acceptance remain separate gates.
@@ -2,7 +2,8 @@
2
2
 
3
3
  Use `agentpay` after installing the package or linking a source checkout with
4
4
  `npm link`. From a source folder, `./run` is the same entry; it uses Node on PATH
5
- or `AGENTPAY_NODE`.
5
+ or `AGENTPAY_NODE`. For a folder-local npm install, use
6
+ `./node_modules/.bin/agentpay`; its `update` stays in that installation folder.
6
7
 
7
8
  ```sh
8
9
  agentpay help
@@ -8,18 +8,35 @@ For a global npm installation:
8
8
  agentpay update
9
9
  ```
10
10
 
11
+ For an npm installation inside a project folder, run its own command:
12
+
13
+ ```sh
14
+ ./node_modules/.bin/agentpay update
15
+ ```
16
+
17
+ Directory-local update support starts with User 0.3.3. For an older directory
18
+ installation, run `npm install --save-exact @c4roa0/agentpay-user@0.3.3` in its
19
+ original program folder, then `./node_modules/.bin/agentpay repair`. Future versions
20
+ can be installed with the command above. Keep your private data directory.
21
+
22
+ Both forms update the installation that owns the command, regardless of the
23
+ terminal's working directory. Directory installs update their direct User dependency
24
+ and package lockfile in that folder, with an exact version; global installs keep
25
+ their global prefix. The confirmation shows the target folder. User must be a direct
26
+ registry dependency, not a transitive dependency or a linked/custom-source package.
27
+
11
28
  It checks the published User version and shows its exact Wallet dependency. Confirm
12
29
  to continue, or cancel without changing services. `agentpay update -f` skips only
13
- this confirmation. The updater checks requirements, stops configured services,
30
+ this confirmation. The updater checks requirements in a temporary installation directory, stops configured services,
14
31
  installs the confirmed version and invokes the new version's repair to refresh
15
32
  services and verify its pinned official test Skill. No paid test runs automatically.
16
33
  Other installed Skills and original requests are kept. Wallet needs unlocking after
17
34
  restart. A current User version still checks the official test Skill.
18
35
 
19
- Only genuine global npm installations are updated. A source checkout or `npm link`
36
+ Only genuine npm installations are updated. A source checkout or `npm link`
20
37
  is refused rather than overwritten: update User's files, run `npm ci`, then
21
- `agentpay repair`. The first User 0.3.0 release establishes the package baseline; a later real
22
- registry upgrade still needs participant acceptance. The updater uses npm's configured registry, checks
38
+ `agentpay repair`. Directory update has controlled real-npm verification; participant upgrade acceptance
39
+ remains separate. The updater uses npm's configured registry, checks
23
40
  Node engine requirements and disables package installation hooks; releases must
24
41
  ship usable runtime artifacts. It never independently selects the newest Wallet.
25
42
 
@@ -1,56 +1,62 @@
1
1
  # Publish User to npm
2
2
 
3
- This publishes the User CLI and Runtime, with its exact reviewed Wallet dependency.
4
- It does not deploy platform services or alter participant keys, Policies or Orders.
3
+ Push a reviewed `vX.Y.Z` tag to publish `@c4roa0/agentpay-user` through GitHub
4
+ Actions. The tag must match `package.json`. Ordinary branch pushes do not publish.
5
+ Keep `update-pair.json`, the lockfile and the reviewed Wallet dependency aligned.
6
+ Publish the required Wallet version before releasing User.
5
7
 
6
- ## Verify a release
8
+ ## One-time setup
7
9
 
8
- From a clean reviewed source checkout, using Node 22.22.3 or newer:
10
+ In GitHub **Settings → Environments → npm-publish**, allow deployment from tags
11
+ matching `v*`. A rule allowing only the `main` branch will block tag releases.
12
+ Keep required reviewer approval if desired. Restrict creation, update and deletion
13
+ of release tags to maintainers through repository rules.
9
14
 
10
- ```sh
11
- npm ci --ignore-scripts
12
- npm test
13
- node scripts/test-package.mjs artifacts/npm
14
- ```
15
+ On npm, configure this package's Trusted Publisher:
16
+
17
+ | Field | Value |
18
+ | --- | --- |
19
+ | Publisher | GitHub Actions |
20
+ | Organization/user | `c4rO-0` |
21
+ | Repository | `agentpay-user` |
22
+ | Workflow filename | `publish.yml` |
23
+ | Environment name | `npm-publish` |
24
+ | Allowed action | Direct publishing |
15
25
 
16
- Review the package inventory and README. The archive check installs the package in
17
- an isolated directory, checks the public command and starts disposable Wallet/Runtime
18
- processes. It never uses a participant's private data. Keep the exact verified archive
19
- for publication; do not rebuild it between verification and upload.
26
+ Existing matching npm trust settings need no change. The first successful OIDC
27
+ publication validates a pending connection; a local token upload does not.
28
+ No stored npm token is needed by this workflow.
20
29
 
21
- ## First publication
30
+ ## Release a version
22
31
 
23
- Authenticate as the package maintainer, then publish the verified archive:
32
+ 1. Update `package.json` and the changelog. Review code, documentation, dependencies
33
+ and package contents; complete the repository's verification steps.
34
+ 2. Commit and push the reviewed source to main, including the tag-triggered workflow.
35
+ 3. Create an annotated tag at that exact commit and push it. Replace `X.Y.Z` and
36
+ `REVIEWED_COMMIT` below with the release version and reviewed commit:
24
37
 
25
38
  ```sh
26
- npm publish artifacts/npm/c4roa0-agentpay-user-0.3.0.tgz --access public --ignore-scripts --registry=https://registry.npmjs.org/
27
- node scripts/verify-npm-release.mjs artifacts/npm/c4roa0-agentpay-user-0.3.0.tgz 0.3.0
39
+ git tag -a vX.Y.Z REVIEWED_COMMIT -m "Release X.Y.Z"
40
+ git push origin vX.Y.Z
28
41
  ```
29
42
 
30
- Never commit or share a publishing Token. If npm stages the first release, approve
31
- it on npm before verifying. A timeout is not proof of failure: check the registry
32
- before retrying publication. Published version numbers cannot be reused.
33
-
34
- ## GitHub Trusted Publisher
43
+ Pushing the tag starts **Publish User to npm** automatically. There is no version
44
+ input or separate Run workflow step. If the environment requires approval, approve
45
+ that deployment in GitHub. The workflow checks the tag against the manifest before
46
+ building, runs the existing verification gates, tests/packs the archive, publishes
47
+ with OIDC and checks public registry integrity. It builds the tagged source, even
48
+ if main advances. No production service or participant Wallet is upgraded.
35
49
 
36
- Create the GitHub environment `npm-publish` and restrict its deployment branch to
37
- `main`. Add maintainer approval if desired. In the npm package's Trusted Publisher
38
- settings, select GitHub Actions and enter:
50
+ ## Verify or recover a publication
39
51
 
40
- | Field | Value |
41
- | --- | --- |
42
- | Organization/user | `c4rO-0` |
43
- | Repository | `agentpay-user` |
44
- | Workflow filename | `publish.yml` |
45
- | Environment name | `npm-publish` |
46
- | Allowed action | Direct publishing |
52
+ Check the run's **Verify public registry integrity** result and the package version
53
+ on npm. Record the tag, source commit and result in progress. Do not claim success
54
+ from tag creation alone. Actual OIDC validation requires the GitHub run.
47
55
 
48
- Run **Publish User to npm** on `main` with a new reviewed package version matching
49
- `package.json` and `update-pair.json`. It tests, packs, verifies, publishes that exact
50
- archive through OIDC, and compares registry integrity. No stored npm Token is needed.
51
- The first successful OIDC release validates the connection; the initial Token upload
52
- does not. Afterwards, disable bypass-2FA tokens and retire unused publishing tokens.
53
- See [npm Trusted Publishing](https://docs.npmjs.com/trusted-publishers/).
56
+ If a run fails before upload, investigate before rerunning. If source needs a fix,
57
+ use a new version/tag; never move an existing release tag. If upload may have
58
+ succeeded, check registry state and archive integrity before rerunning; npm versions
59
+ are immutable and an already-published version must not be uploaded again.
54
60
 
55
- Publication is not real-network or participant upgrade acceptance. Record the exact
56
- source revision and verification outcome; test the published installation separately.
61
+ Publication is not participant upgrade acceptance, cross-platform verification or
62
+ real-funds approval.
@@ -9,9 +9,24 @@ hash reported by the same server that supplies the ZIP.
9
9
 
10
10
  This pin applies only to the maintained onboarding test. Generic Runtime calls and
11
11
  ordinary Skill installation do not require the random service or this package.
12
- The current pin is the reviewed random Skill 1.2.0 private rehearsal package;
12
+ The current pin is the reviewed random Skill 1.2.1 private rehearsal package;
13
13
  it includes its service reference. It is not a production-network release.
14
14
 
15
+ ## Download a fixed Market version
16
+
17
+ Setup and repair derive `/skills/bundles/:serviceId/versions/:sha256/metadata`
18
+ from the saved Market source, using User's built-in ZIP hash. They download the matching
19
+ fixed ZIP on the same origin and retain any `/market` ingress prefix. They no longer
20
+ require Market's current release to match the User release. The ZIP is still hashed
21
+ before parsing or saving; metadata cannot override the pin.
22
+
23
+ Market must retain the approved historical version and permit its public download.
24
+ If it is absent, withdrawn or no longer approved under current checks, preparation
25
+ stops with an unavailable message. No current-version or Provider-hosted fallback is
26
+ used. Existing local packages, requests and spending permission are unchanged.
27
+ This client change requires the Market fixed-version API rollout before distributing
28
+ the next User release; User 0.3.1 and earlier do not use this endpoint.
29
+
15
30
  ## Before publishing a User update
16
31
 
17
32
  1. Check whether the maintained official Skill has a new published version.
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@c4roa0/agentpay-user",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "type": "module",
5
5
  "dependencies": {
6
- "ethers": "^6.17.0",
7
- "fs-native-extensions": "1.5.3",
8
6
  "@c4roa0/agentpay-protocol": "0.14.3",
9
- "@c4roa0/agentpay-wallet": "0.3.1"
7
+ "@c4roa0/agentpay-wallet": "0.3.2",
8
+ "ethers": "^6.17.0",
9
+ "fs-native-extensions": "1.5.3"
10
10
  },
11
11
  "scripts": {
12
12
  "start": "node src/index.mjs",
package/progress.md CHANGED
@@ -1,6 +1,147 @@
1
1
  # AgentPay User progress
2
2
 
3
- ## User 0.3.1 paired release preparation — 2026-11-08
3
+ ## User 0.3.3 release candidate — 2026-11-09
4
+
5
+ Release directory-local npm updates, keeping exact Wallet 0.3.2 and Protocol
6
+ 0.14.3 dependencies and the reviewed official test package unchanged. No endpoint
7
+ migration, Policy or saved request rewrite is included. All 383 local behavior tests and independent archive installation/process checks
8
+ passed. Tag-triggered publication and registry verification remain pending.
9
+
10
+ ## HTTPS endpoint migration — 2026-11-09
11
+
12
+ HTTPS migration inventory: existing setup rejects URL differences; local service settings, Market receipt origin/session, recovery observations and cancellation intents need coordinated handling. Public configuration publication does not migrate existing users. Keep original requests/Policies and current tunnels until an explicit local migration is implemented and verified.
13
+
14
+ ## Directory npm update — 2026-11-08
15
+
16
+ Update now supports a direct registry dependency under a project node_modules as
17
+ well as a global installation. It derives the owning project from the running
18
+ package, pins the confirmed version, preserves the dependency section, updates the
19
+ local lockfile and uses the existing stop/repair/private-data flow. Source/link,
20
+ custom-source and transitive installs are refused before changing services.
21
+ Nine updater regression checks passed. A real public-npm 0.3.1 → 0.3.2 upgrade
22
+ in a disposable project verified program/manifest/lockfile agreement and preserved
23
+ private-record fixtures; service hooks were controlled, not participant processes.
24
+ This exposed npm dry-run rewriting the hidden installed-tree lockfile. Preflight
25
+ now runs in a disposable prefix with private project npm settings, removed afterward.
26
+ See [verification](doc/records/local-npm-update-2026-11-08.md).
27
+ User 0.3.3 is the release candidate for this fix; publication verification is pending.
28
+
29
+ ## User 0.3.2 tag publication verified — 2026-11-08
30
+
31
+ Tag `v0.3.2` points to `890171b`; GitHub push-triggered OIDC run
32
+ [42491753287](https://github.com/c4rO-0/agentpay-user/actions/runs/42491753287)
33
+ completed successfully, including registry integrity verification. Public npm latest
34
+ is 0.3.2, pins Wallet 0.3.2 / Protocol 0.14.3 and includes provenance. Independently
35
+ downloaded registry bytes exactly match the locally tested archive (SHA-256
36
+ `e6bb2f1199e510850313c004055afeb3ba45afc07035697c1d37af14ebcf1489`).
37
+ All 380 existing tests and the independent package's real Wallet/Runtime restart
38
+ check passed. Participant npm update/restart acceptance remains the next step;
39
+ publication did not modify any participant services or create a paid Order.
40
+
41
+ ## User 0.3.2 release pairing — 2026-11-08
42
+
43
+ Candidate now pins the verified public Wallet 0.3.2 with Protocol 0.14.3; package,
44
+ lockfile and update-pair metadata agree. This release includes fixed-version
45
+ Market downloads and the reviewed official Skill 1.2.1 pin. Historical notes
46
+ below describe earlier candidate pairings. Publish through tag `v0.3.2` after
47
+ final suite and standalone archive checks; no automatic new purchase is authorized.
48
+
49
+ ## Tag-triggered publication — 2026-11-08
50
+
51
+ Wallet, Protocol and User release workflows now run on pushed `vX.Y.Z` tags.
52
+ Each validates its package version, runs existing verification, publishes with
53
+ OIDC and checks registry integrity. Branch pushes do not publish. No tag was
54
+ pushed or npm version published for this workflow change. Owner confirmed `v*` tags allowed in the GitHub
55
+ `npm-publish` environment; npm trust fields remain unchanged. YAML/shell checks and six executable tag/version guard cases passed
56
+ per repository (matching version, mismatch, branch, prerelease, leading zero and
57
+ newline rejection). Actual GitHub/OIDC execution remains pending.
58
+
59
+ ## Official 1.2.1 payment reconciled / User 0.3.2 candidate — 2026-11-08
60
+
61
+ Participant confirmed Market Order visibility. Independent fixed-block chain reads,
62
+ receipts and token transfers match Settlement's finalized release record: paid
63
+ 0.7 rUSDC, seller 0.665, platform fee 0.035, no refund, empty Vault. Funding,
64
+ delivery and release events occur once for the verified Order. No further payment.
65
+ This is private Anvil acceptance, not real-network or production approval.
66
+ User 0.3.2 candidate includes fixed-version downloads and the reviewed official
67
+ 1.2.1 ZIP pin. Its preliminary package check used Wallet 0.3.1 and Protocol 0.14.3.
68
+ The maintainer requested Wallet 0.3.2 review/publication first; after registry
69
+ verification, update User’s exact dependency and reverify the final package.
70
+ Candidate publication and real npm update acceptance remain pending.
71
+
72
+ ## Official Skill 1.2.1 participant payment passed — 2026-11-08
73
+
74
+ Operator ran normal wallet unlock and payment-test commands after source repair.
75
+ The guide quoted a maximum 0.7 rUSDC and 10-minute service limit; the operator
76
+ explicitly confirmed. It reported delivery verification, saved-result verification
77
+ and receipt acknowledgement, then completed successfully. This is private Anvil
78
+ end-to-end participant evidence. The quoted maximum is not independently reconciled
79
+ actual charge; payout/refund terminal chain evidence has not been checked here.
80
+ User remains the 0.3.1-labelled source candidate, not a new published npm release.
81
+ Next: website Order visibility and read-only Settlement/chain reconciliation before
82
+ release closeout. Do not rerun a completed payment test just to inspect the result.
83
+
84
+ ## Participant repair completed — 2026-11-08
85
+
86
+ Operator ran the normal source repair entry. Official Skill 1.2.1 passed the
87
+ built-in hash check and was installed. Wallet and Runtime restarted; Wallet is
88
+ locked as expected. Saved Policy and Market connection remain present, and local
89
+ history reports two settled Orders plus one archived record. No purchase occurred.
90
+ This is source-candidate repair acceptance, not publication of a new npm version.
91
+ Next operator step unlocks Wallet and invokes the normal payment test; explicit
92
+ current-price confirmation remains required before creating a paid Order.
93
+
94
+ ## Official fixed-download acceptance — 2026-11-08
95
+
96
+ The normal prepareOfficialTestUpdate entry downloaded 1.2.1 twice from the running
97
+ Market fixed-version API into an isolated directory, verified the built-in hash,
98
+ installed successfully and preserved an existing prior-record fixture byte-for-byte.
99
+ The first diagnostic read assumed a flat archive; it was corrected to read the saved
100
+ publisher ZIP through User's parser. No product installation defect was found.
101
+ 17 targeted pin/download/update/payment-orchestration/prefix checks passed.
102
+ This proves download/install behavior, not paid invocation. No participant services
103
+ or Wallet data changed. Source repair and explicit payment acceptance are next;
104
+ the candidate is not yet a new npm release.
105
+
106
+ ## Official test pin 1.2.1 prepared — 2026-11-08
107
+
108
+ Reviewed the actual Provider ZIP and confirmed it matches the published fixed Market
109
+ download: 4373 bytes, SHA-256
110
+ `20633b314c66166f94dc6e7d7eb5bce54ab5901fb1ed314a04ea3fd49ca8a9a4`.
111
+ The official-test pin now selects 1.2.1; generic Runtime routing is unchanged.
112
+ The package checker and 14 controlled pin/download/update/payment-orchestration
113
+ checks passed. The payment fixture now follows the selected version instead of
114
+ hardcoding 1.2.0. No real payment, service restart or npm release was performed.
115
+ Before participant testing, check for unfinished tests from the previous version:
116
+ records are retained, but the payment-test entry selects a version-specific record.
117
+ Do not treat a new-version test as recovery of an old purchase.
118
+
119
+
120
+ ## Development dependency verification — 2026-11-08
121
+
122
+ Reinstalled dependencies from the unchanged lockfile after a stale local installation
123
+ could not resolve the already-declared Protocol package. Fixed-download/update/prefix
124
+ checks pass 8/8; the cross-repository publication/download/User preview regression
125
+ passes 27/27. No dependency pins, services or user data changed. This is controlled
126
+ verification, not a new npm release or live payment acceptance.
127
+
128
+
129
+ ## Fixed historical Skill downloads — 2026-11-08
130
+
131
+ Development adds SHA-256-fixed Market metadata/ZIP routes over retained releases,
132
+ a derived per-listing lookup, website forwarding and User official-test pin selection.
133
+ Current publication replacement no longer changes the requested ZIP. Hidden/deleted
134
+ listings, takedown, stale approval and damaged files remain unavailable. Historical
135
+ internal-version ZIP routes now also respect listing visibility. No DB migration,
136
+ Provider download dependency, service restart or payment was performed.
137
+ Deploy Market API/Web and the nginx route allowlist first, then release the updated User; current published User
138
+ 0.3.1 does not use the new fixed-version endpoint. Verification: User 33 targeted checks, Web 7 proxy checks, Deploy 8 route/build checks
139
+ and both Market/Web typechecks passed. Market publication regression: 69/70 passed;
140
+ the remaining pre-existing schema fixture fails with WALLET_MAPPING_SCHEMA_INVALID.
141
+ Controlled scanner/DB fixtures and local HTTP were used; no live database, nginx
142
+ rollout or participant acceptance is claimed.
143
+
144
+ ## User 0.3.1 paired release published — 2026-11-08
4
145
 
5
146
  Public npm now contains Wallet 0.3.1 with Protocol 0.14.3. User 0.3.1 pins that
6
147
  published Wallet exactly; pairing metadata and lockfile are updated together.
@@ -8,10 +149,19 @@ This release adds actual installed Protocol verification and running-version che
8
149
  for status/repair. Prior release-gate notes below describe earlier checkpoints.
9
150
  User 0.3.1 passed 378 behavioral tests and standalone npm archive installation,
10
151
  including real Wallet/Runtime restart and matching running-version reports.
11
- User 0.3.1 publication and real published-version upgrade acceptance remain pending.
152
+ User 0.3.1 is public and npm `latest`, with Wallet 0.3.1 and Protocol 0.14.3.
153
+ [User OIDC publication](https://github.com/c4rO-0/agentpay-user/actions/runs/42440841342)
154
+ passed from `46796ea`; [Wallet OIDC publication](https://github.com/c4rO-0/agentpay-wallet/actions/runs/42440112081)
155
+ passed from `7e4d4fa`. Registry metadata was independently checked.
156
+ Real published-version upgrade/restart acceptance remains pending.
12
157
  No participant services, keys, Policies or Orders are changed by package verification.
13
158
 
14
- ## Installed dependency verification / paired release — 2026-11-08
159
+ ## Historical checkpoints — superseded by the current release status above
160
+
161
+ The dated entries below preserve evidence and earlier decisions. Their pending
162
+ release labels are historical; use current TODO for remaining work.
163
+
164
+ ### Installed dependency verification / paired release — 2026-11-08
15
165
 
16
166
  User now checks the actual Protocol package resolved from User and Wallet separately,
17
167
  including nested npm copies. Process reports use resolved installed versions, not
@@ -7,7 +7,7 @@ import {
7
7
  verifyOfficialTestBytes,
8
8
  verifyOfficialTestDigest,
9
9
  } from "../src/official-test-package.mjs";
10
- import { marketDownloadUrl } from "../src/market-download-url.mjs";
10
+ import { marketDownloadUrl, marketVersionMetadataUrl } from "../src/market-download-url.mjs";
11
11
  import { resolve } from "node:path";
12
12
  import {
13
13
  inspectInstalledBundle,
@@ -42,7 +42,7 @@ if (
42
42
  }
43
43
  if (mode === "--prepare-official-test" && !marketMode)
44
44
  throw Error("OFFICIAL_TEST_MARKET_REQUIRED");
45
- const url = new URL(source);
45
+ const url = official ? marketVersionMetadataUrl(source, digest) : new URL(source);
46
46
  if (
47
47
  url.username ||
48
48
  url.password ||
@@ -62,6 +62,8 @@ if (marketMode) {
62
62
  redirect: "error",
63
63
  signal: AbortSignal.timeout(5000),
64
64
  });
65
+ if (official && [404, 410].includes(r.status))
66
+ throw Error("This official test version is unavailable in Market. Check for a reviewed User update or contact support; no replacement was selected.");
65
67
  if (!r.ok) throw new Error(`MARKET_BUNDLE_METADATA_HTTP_${r.status}`);
66
68
  const body = await r.json();
67
69
  metadata = body.result;
@@ -78,7 +80,7 @@ if (marketMode) {
78
80
  !metadata.publisherId ||
79
81
  typeof metadata.marketServiceId !== "string" ||
80
82
  metadata.marketDownloadPath !==
81
- `/skills/bundles/${encodeURIComponent(metadata.marketServiceId)}/download`
83
+ marketDownloadUrl(url, metadata.marketServiceId).pathname.replace(/^\/market(?=\/skills\/)/, "")
82
84
  )
83
85
  throw new Error("MARKET_BUNDLE_METADATA_INVALID");
84
86
  downloadUrl = marketDownloadUrl(url, metadata.marketServiceId);
@@ -1,21 +1,26 @@
1
1
  // SPDX-License-Identifier: MPL-2.0
2
2
  // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
3
3
  // If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
4
- // Preserve the approved metadata URL's ingress prefix; metadata cannot select a host.
4
+ // The configured origin/prefix owns the download location; metadata cannot change it.
5
+ function metadataLocation(value) {
6
+ const url = new URL(value);
7
+ const match = /^(|\/market)\/skills\/bundles\/([^/]+)(?:\/versions\/([a-f0-9]{64}))?\/metadata$/.exec(url.pathname);
8
+ if (url.username || url.password || url.search || url.hash || !match)
9
+ throw Error('MARKET_METADATA_PATH_MISMATCH');
10
+ return { url, prefix: match[1], service: match[2], digest: match[3] };
11
+ }
12
+
13
+ export function marketVersionMetadataUrl(source, digest) {
14
+ const location = metadataLocation(source);
15
+ if (!/^[a-f0-9]{64}$/.test(digest) || location.digest && location.digest !== digest)
16
+ throw Error('MARKET_PACKAGE_VERSION_MISMATCH');
17
+ location.url.pathname = `${location.prefix}/skills/bundles/${location.service}/versions/${digest}/metadata`;
18
+ return location.url;
19
+ }
20
+
5
21
  export function marketDownloadUrl(metadataUrl, serviceId) {
6
- const url = new URL(metadataUrl);
7
- const suffix = `/skills/bundles/${encodeURIComponent(serviceId)}/metadata`;
8
- if (
9
- url.username ||
10
- url.password ||
11
- url.search ||
12
- url.hash ||
13
- !url.pathname.endsWith(suffix)
14
- )
15
- throw Error("MARKET_METADATA_PATH_MISMATCH");
16
- const prefix = url.pathname.slice(0, -suffix.length);
17
- if (!["", "/market"].includes(prefix))
18
- throw Error("MARKET_METADATA_PREFIX_INVALID");
19
- url.pathname = prefix + suffix.replace(/\/metadata$/, "/download");
22
+ const {url, service} = metadataLocation(metadataUrl);
23
+ if (service !== encodeURIComponent(serviceId)) throw Error('MARKET_METADATA_PATH_MISMATCH');
24
+ url.pathname = url.pathname.replace(/\/metadata$/, '/download');
20
25
  return url;
21
26
  }
@@ -1,11 +1,11 @@
1
1
  // SPDX-License-Identifier: MPL-2.0
2
- // Update only a real global npm installation. Source checkouts/npm links are never
2
+ // Update real global or project npm installations. Source checkouts/npm links are never
3
3
  // overwritten. npm selects User; User's exact dependencies select Wallet/Protocol.
4
4
  import { execFile } from 'node:child_process';
5
5
  import { promisify } from 'node:util';
6
- import { access, appendFile, lstat, mkdir, open, readFile, realpath, unlink } from 'node:fs/promises';
6
+ import { access, appendFile, copyFile, chmod, lstat, mkdir, mkdtemp, open, readFile, realpath, rm, unlink } from 'node:fs/promises';
7
7
  import { constants } from 'node:fs';
8
- import { dirname, isAbsolute, join } from 'node:path';
8
+ import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
9
9
  import { randomUUID } from 'node:crypto';
10
10
  import { createInterface } from 'node:readline/promises';
11
11
  import { installedUserDir, resolveUserDataDir, rememberUserDataDir } from './local-data-directory.mjs';
@@ -35,6 +35,35 @@ async function askConfirmation(message) {
35
35
  const terminal = createInterface({ input:process.stdin, output:process.stdout });
36
36
  try { return await terminal.question(message + '\n> '); } finally { terminal.close(); }
37
37
  }
38
+ // Resolve the installed package, not the terminal's working directory. A project
39
+ // update must name a direct dependency; never promote a transitive package or
40
+ // replace a linked source checkout as a side effect of updating User.
41
+ async function installationTarget(userDir, npm) {
42
+ const root = await npm(['root', '--global']);
43
+ if (!isAbsolute(root)) throw Error('npm installation paths could not be verified.');
44
+ const globalPath = join(root, name);
45
+ const info = await lstat(globalPath).catch(e => { if (e.code !== 'ENOENT') throw e; return null; });
46
+ if (info?.isDirectory() && !info.isSymbolicLink() && await realpath(globalPath) === await realpath(userDir)) {
47
+ const prefix = await npm(['prefix', '--global']);
48
+ if (!isAbsolute(prefix)) throw Error('npm installation paths could not be verified.');
49
+ return {prefix, flags:['--global'], directory:globalPath};
50
+ }
51
+ const scope = dirname(userDir), modules = dirname(scope), prefix = dirname(modules);
52
+ if (basename(userDir) !== 'agentpay-user' || basename(scope) !== '@c4roa0' || basename(modules) !== 'node_modules' ||
53
+ !(await lstat(userDir)).isDirectory() || (await lstat(userDir)).isSymbolicLink())
54
+ throw Error('This is a source checkout or linked installation. Update its files, run npm ci, then agentpay repair.');
55
+ const project = JSON.parse(await readFile(join(prefix,'package.json'),'utf8'));
56
+ const sections = ['dependencies','devDependencies','optionalDependencies'].filter(key => Object.hasOwn(project[key] || {}, name));
57
+ if (sections.length !== 1 || typeof project[sections[0]][name] !== 'string')
58
+ throw Error('User must be a direct npm dependency of this folder. Install it in a dedicated folder before using update.');
59
+ const spec = project[sections[0]][name];
60
+ if (/[:/\\]/.test(spec) || spec.startsWith('.'))
61
+ throw Error('This dependency uses a custom source. Update that source explicitly, then run agentpay repair.');
62
+ const save = {dependencies:'--save-prod',devDependencies:'--save-dev',optionalDependencies:'--save-optional'}[sections[0]];
63
+ return {prefix, directory:userDir, section:sections[0], spec,
64
+ flags:['--global=false','--workspaces=false','--save-exact',save,'--include=dev','--include=optional']};
65
+ }
66
+
38
67
  export async function updateFromNpm({
39
68
  userDir = installedUserDir, dataDir, force = false, write = console.log,
40
69
  ask = askConfirmation,
@@ -45,17 +74,13 @@ export async function updateFromNpm({
45
74
  } = {}) {
46
75
  let lock, lockPath, logPath, installing = false;
47
76
  try {
77
+ userDir = resolve(userDir);
48
78
  const current = JSON.parse(await readFile(join(userDir, 'package.json'), 'utf8'));
49
79
  if (current.name !== name || !stable(current.version)) throw Error('Unrecognized User installation.');
50
80
  write('Checking for a User update…');
51
- const root = await npm(['root','--global']), prefix = await npm(['prefix','--global']);
52
- if (!isAbsolute(root) || !isAbsolute(prefix)) throw Error('npm installation paths could not be verified.');
53
- const globalPath = join(root, name);
54
- const globalInfo = await lstat(globalPath).catch(e => { if(e.code !== 'ENOENT') throw e; return null; });
55
- if (!globalInfo || globalInfo.isSymbolicLink() || await realpath(globalPath) !== await realpath(userDir))
56
- throw Error('This is a source checkout or linked installation. Update its files, run npm ci, then agentpay repair.');
57
- await access(dirname(globalPath), constants.W_OK);
58
- const metadata = JSON.parse(await npm(['view',name + '@latest','--global','--json']));
81
+ const target = await installationTarget(userDir, npm);
82
+ await access(dirname(target.directory), constants.W_OK);
83
+ const metadata = JSON.parse(await npm(['view',name + '@latest','--json'], {cwd:target.prefix}));
59
84
  if (metadata.name !== name || !stable(metadata.version) ||
60
85
  !stable(metadata.dependencies?.['@c4roa0/agentpay-wallet']) ||
61
86
  !stable(metadata.dependencies?.['@c4roa0/agentpay-protocol']))
@@ -67,6 +92,7 @@ export async function updateFromNpm({
67
92
  return 0;
68
93
  }
69
94
  write(`User ${current.version} → ${metadata.version} · Wallet ${metadata.dependencies['@c4roa0/agentpay-wallet']}`);
95
+ write(`Installation folder: ${target.prefix}`);
70
96
  write('Background services will pause. Keys, permissions, Orders and cache are kept.');
71
97
  if (!force && (await ask("Type 'confirm' to update, or 'q' to cancel")).trim().toLowerCase() !== 'confirm') {
72
98
  write('Update cancelled. Nothing was changed.'); return 0;
@@ -81,12 +107,28 @@ export async function updateFromNpm({
81
107
  const rechecked = JSON.parse(await readFile(join(userDir,'package.json'),'utf8'));
82
108
  if (rechecked.version !== current.version || rechecked.name !== name)
83
109
  throw Error('Program files changed while reviewing the update. Run agentpay update again.');
110
+ if (target.section) {
111
+ const project = JSON.parse(await readFile(join(target.prefix,'package.json'),'utf8'));
112
+ if (project[target.section]?.[name] !== target.spec)
113
+ throw Error('The project dependency changed while reviewing the update. Run agentpay update again.');
114
+ }
84
115
  const env = {...process.env,AGENTPAY_USER_DATA_DIR:dataDir};
85
- const options = {logPath,env,cwd:stateDir,timeout:600000};
116
+ const options = {logPath,env,cwd:target.prefix,timeout:600000};
86
117
  const spec = name + '@' + metadata.version;
87
- const args = ['install','--global','--prefix',prefix,'--engine-strict','--ignore-scripts','--no-audit','--no-fund',spec];
118
+ const args = ['install',...target.flags,'--prefix',target.prefix,'--engine-strict','--ignore-scripts','--no-audit','--no-fund',spec];
88
119
  write('1/3 Check the update requirements.');
89
- await npm([...args,'--dry-run'],options);
120
+ // npm dry-run may rewrite its hidden installed-tree lockfile. Preflight in
121
+ // a disposable prefix, never the live installation. Carry project npm settings
122
+ // privately so registry/auth selection remains consistent with the real install.
123
+ const preflight = await mkdtemp(join(stateDir,'update-check-'));
124
+ try {
125
+ await copyFile(join(target.prefix,'.npmrc'),join(preflight,'.npmrc')).then(
126
+ () => chmod(join(preflight,'.npmrc'),0o600),
127
+ error => { if(error.code !== 'ENOENT') throw error; });
128
+ await npm(['install','--global=false','--prefix',preflight,'--engine-strict',
129
+ '--ignore-scripts','--no-audit','--no-fund',spec,'--dry-run'],
130
+ {...options,cwd:preflight});
131
+ } finally { await rm(preflight,{recursive:true,force:true}); }
90
132
  let configured = false;
91
133
  try { configured = (await lstat(join(dataDir,'runtime/local-services.json'))).isFile(); }
92
134
  catch(e) { if(e.code !== 'ENOENT') throw e; }
@@ -8,8 +8,8 @@ import { createHash } from "node:crypto";
8
8
  // This belongs to the official onboarding test, never generic Runtime routing.
9
9
  export const OFFICIAL_TEST_PACKAGE = Object.freeze({
10
10
  name: "agentpay-random",
11
- version: "1.2.0",
12
- sha256: "aa366fc2e747b5b444786d542b0a412a505e58ea15252ac1a792b99079084146",
11
+ version: "1.2.1",
12
+ sha256: "20633b314c66166f94dc6e7d7eb5bce54ab5901fb1ed314a04ea3fd49ca8a9a4",
13
13
  });
14
14
  const mismatch = () =>
15
15
  Object.assign(
@@ -10,7 +10,7 @@ import {
10
10
  verifyOfficialTestBytes,
11
11
  verifyOfficialTestDigest,
12
12
  } from "./official-test-package.mjs";
13
- import { marketDownloadUrl } from "./market-download-url.mjs";
13
+ import { marketDownloadUrl, marketVersionMetadataUrl } from "./market-download-url.mjs";
14
14
 
15
15
  async function localJson(path) {
16
16
  let handle;
@@ -48,6 +48,8 @@ async function download(fetchImpl, address, max) {
48
48
  redirect: "error",
49
49
  signal: AbortSignal.timeout(10000),
50
50
  });
51
+ if ([404, 410].includes(response.status))
52
+ throw Object.assign(Error("Official test version unavailable"), {code: "OFFICIAL_TEST_VERSION_UNAVAILABLE"});
51
53
  if (!response.ok || !response.body) throw Error("Market request failed");
52
54
  let length = 0;
53
55
  const chunks = [];
@@ -99,13 +101,7 @@ export async function prepareOfficialTestUpdate({
99
101
  );
100
102
  return { status: "unconfigured" };
101
103
  }
102
- const metadataUrl = url(source);
103
- if (
104
- !/^\/(?:market\/)?skills\/bundles\/[^/]+\/metadata$/.test(
105
- metadataUrl.pathname,
106
- )
107
- )
108
- throw Error("Invalid package metadata path");
104
+ const metadataUrl = marketVersionMetadataUrl(url(source), OFFICIAL_TEST_PACKAGE.sha256);
109
105
  const body = JSON.parse(
110
106
  (await download(fetchImpl, metadataUrl, 65536)).toString("utf8"),
111
107
  );
@@ -150,6 +146,8 @@ export async function prepareOfficialTestUpdate({
150
146
  write(
151
147
  "Not updated: the published ZIP does not match this User release. Check for a reviewed User update; do not bypass the file check.",
152
148
  );
149
+ else if (error.code === "OFFICIAL_TEST_VERSION_UNAVAILABLE")
150
+ write("This official test version is unavailable in Market. Check for a reviewed User update or contact support; no replacement package was selected.");
153
151
  else
154
152
  write(
155
153
  "Could not prepare the official test Skill. Check your Market connection and retry agentpay repair.",
package/update-pair.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "format": "agentpay.local-update-pair.v1",
3
- "userVersion": "0.3.1",
4
- "walletVersion": "0.3.1",
3
+ "userVersion": "0.3.3",
4
+ "walletVersion": "0.3.2",
5
5
  "typesDependency": "0.14.3"
6
6
  }