From 185790ec7eaf99b3e4b8845e808ea4cc47e31688 Mon Sep 17 00:00:00 2001 From: blckbx <74455114+blckbx@users.noreply.github.com> Date: Fri, 28 Aug 2026 11:23:47 +0200 Subject: [PATCH] chore(release): prepare 0.1.2 for OpenClaw 2026.6.34 --- AGENTS.md | 2 +- README.md | 16 +- SECURITY.md | 4 +- docs/IMPLEMENTATION_PLAN.md | 62 +++---- .../01-installable-plugin-and-identity.md | 10 +- .../04-allowlisted-ai-roundtrip.md | 6 +- .../05-pairing-and-dm-policies.md | 2 +- ...7-replay-resilience-and-resource-limits.md | 2 +- .../08-setup-interoperability-and-release.md | 6 +- .../10-nip17-encrypted-media-ingress.md | 2 +- package-lock.json | 172 ++++++++++++++---- package.json | 10 +- scripts/validate-host-security.mjs | 4 +- scripts/validate-sdk-imports.mjs | 2 +- src/__tests__/documentation.test.ts | 8 + src/__tests__/metadata.test.ts | 9 +- src/constants.ts | 2 +- 17 files changed, 210 insertions(+), 109 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 62cff40..baf2ba7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ - Follow the ordered slices in `docs/IMPLEMENTATION_PLAN.md` and implement only the active slice. - Use red-green-refactor: observe a focused test fail before implementing behavior, then run focused and full suites. -- Keep TypeScript strict and use public exports from exactly `openclaw@2026.6.1`. +- Keep TypeScript strict and use public exports from exactly `openclaw@2026.6.34`. - Do not read Nostr secret files in plugin code. OpenClaw resolves the configured file SecretRef. - Never log or expose private keys, resolved secret values, plaintext, ciphertext, AUTH challenges, or sender-recipient relationships. - Keep transport, cryptography, and OpenClaw adapter boundaries separate. diff --git a/README.md b/README.md index e2aa86b..7345433 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ npm run package:validate ``` The build checkout intentionally installs development dependencies, including the -pinned OpenClaw `2026.6.1` SDK compatibility baseline. Deployments do not need +pinned OpenClaw `2026.6.34` SDK compatibility baseline. Deployments do not need that development tree. From an npm-managed local OpenClaw `2026.7.2-beta.6` or newer checkout, install the built working directory: @@ -35,9 +35,9 @@ For a standard OpenClaw installation, pack and install the managed artifact: ```bash npm pack -sha256sum openclaw-armada-dm-0.1.1.tgz > openclaw-armada-dm-0.1.1.tgz.sha256 -sha256sum --check openclaw-armada-dm-0.1.1.tgz.sha256 -openclaw plugins install npm-pack:/absolute/path/openclaw-armada-dm-0.1.1.tgz +sha256sum openclaw-armada-dm-0.1.2.tgz > openclaw-armada-dm-0.1.2.tgz.sha256 +sha256sum --check openclaw-armada-dm-0.1.2.tgz.sha256 +openclaw plugins install npm-pack:/absolute/path/openclaw-armada-dm-0.1.2.tgz openclaw plugins enable armada-dm openclaw gateway restart ``` @@ -53,16 +53,16 @@ Maintainers can publish the package and checksum in the repository's Releases section by pushing a version tag after its version bump reaches `main`: ```bash -git tag -a v0.1.1 -m "v0.1.1" -git push origin v0.1.1 +git tag -a v0.1.2 -m "v0.1.2" +git push origin v0.1.2 ``` The tag must exactly match `v` followed by the version in `package.json`. The release workflow repeats the install, test, build, package-validation, pack, and checksum sequence before creating the GitHub release. It attaches -`openclaw-armada-dm-0.1.1.tgz` and its `.sha256` checksum as release assets. +`openclaw-armada-dm-0.1.2.tgz` and its `.sha256` checksum as release assets. -The published `setup-entry.js` uses only the OpenClaw `2026.6.1` public SDK compatibility baseline, while deployment requires patched OpenClaw `2026.7.2-beta.6` or newer. It does not run a wizard, prompt for values, edit configuration, read the secret file, publish events, or start relay connections. +The published `setup-entry.js` uses only the OpenClaw `2026.6.34` public SDK compatibility baseline, while deployment requires patched OpenClaw `2026.7.2-beta.6` or newer. It does not run a wizard, prompt for values, edit configuration, read the secret file, publish events, or start relay connections. ## Migrating another Nostr channel diff --git a/SECURITY.md b/SECURITY.md index 3822f4a..bc4bca9 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,9 +4,9 @@ Report suspected vulnerabilities privately to the repository maintainers. Do not Use a dedicated Nostr bot identity. Store its single `nsec` at `/path/to/.openclaw/secrets/nostr_nsec` in a mode-0700 directory and a mode-0600 file, configure OpenClaw's `nostr` single-value file provider, and reference it from `channels.nostr.privateKey`. The plugin never opens that file directly and must never expose the resolved key through configuration, logs, errors, or status. -Deploy only on OpenClaw `2026.7.2-beta.6` or newer. The plugin deliberately typechecks against the narrower `2026.6.1` public SDK surface for compatibility, but that historical package is a development-only API baseline and is not an approved runtime host. +Deploy only on OpenClaw `2026.7.2-beta.6` or newer. The plugin deliberately compiles and typechecks against the narrower `2026.6.34` public SDK surface for compatibility, but npm currently reports advisories in that exact development-only package tree, so it is not the approved smoke-test or runtime host. -`npm run audit` checks the complete dependency tree as well as production dependencies. It fails for any advisory outside the nested, development-only `openclaw@2026.6.1` SDK baseline, and it independently verifies that the deployable host tree is the patched version above. Current advisories attached to the historical baseline are therefore reported explicitly, never shipped in the plugin package, and never accepted in a runtime host. +`npm run audit` checks the complete dependency tree as well as production dependencies. It fails for any advisory outside the nested, development-only `openclaw@2026.6.34` SDK baseline, and it independently verifies that the deployable host tree is the patched version above. Findings attached to the exact SDK baseline are reported explicitly, never shipped in the plugin package, and never accepted in the runtime smoke host. NIP-17 is transport end-to-end encryption. Plaintext exists on the OpenClaw host and is provided to the operator's configured model provider. Use least-privilege tools and sandboxing for every agent reachable through this channel. diff --git a/docs/IMPLEMENTATION_PLAN.md b/docs/IMPLEMENTATION_PLAN.md index 84d972c..b5bb95b 100644 --- a/docs/IMPLEMENTATION_PLAN.md +++ b/docs/IMPLEMENTATION_PLAN.md @@ -9,7 +9,7 @@ Build a standalone OpenClaw channel plugin that lets people talk privately to an - NIP-59 `kind:13` seals and `kind:1059` gift wraps; - one-to-one direct conversations only. -The plugin should use [`Ink-North/nostr-nip17-plugin`](https://github.com/Ink-North/nostr-nip17-plugin) as the recognizable OpenClaw channel-integration template: package metadata, runtime/setup entry separation, channel registration, runtime injection, the simple `dmPolicy: "allowlist"`/`allowFrom` configuration, and local npm installation. Its legacy portable-bundle metadata and Nostr transport must not be copied blindly; the implementation must use the native plugin contract and public SDK exports available in OpenClaw `2026.6.1` (`2e08f0f`) plus the stricter cryptographic, routing, replay, and lifecycle requirements in this plan. +The plugin should use [`Ink-North/nostr-nip17-plugin`](https://github.com/Ink-North/nostr-nip17-plugin) as the recognizable OpenClaw channel-integration template: package metadata, runtime/setup entry separation, channel registration, runtime injection, the simple `dmPolicy: "allowlist"`/`allowFrom` configuration, and local npm installation. Its legacy portable-bundle metadata and Nostr transport must not be copied blindly; the implementation must use the native plugin contract and public SDK exports available in OpenClaw `2026.6.34` plus the stricter cryptographic, routing, replay, and lifecycle requirements in this plan. [`Tunnelsats/nostr-community-bot`](https://github.com/Tunnelsats/nostr-community-bot) is only a technical reference for Nostr cryptography, relay lifecycle, replay protection, and tests. The plugin has no TunnelSats product, identity, namespace, business-logic, or runtime dependency. @@ -29,7 +29,7 @@ This plan is based on the following implementations and specifications as of 202 - [`nostr-community-bot` at `7ecc4b4`](https://github.com/Tunnelsats/nostr-community-bot/tree/7ecc4b4053a961f163e428fc08e487b07e571e72), especially `src/nip17-dm.ts`, `src/relay-connection-manager.ts`, `src/bot.ts`, and their Vitest suites; - [`Ink-North/nostr-nip17-plugin` at `e824a82`](https://github.com/Ink-North/nostr-nip17-plugin/tree/e824a82e04eea27aa7a237b7feeeca9bead3e0d1), especially its `package.json`, `openclaw.plugin.json`, portable runtime/setup entry separation, channel registration, runtime injection, and simple allowlist configuration. Its package-name mismatch, legacy portable-bundle shape, permissive schemas, NIP-04 support, outer-event dedupe, and direct relay transport are explicitly not normative for this project; - [Armada at `5b99f88`](https://github.com/soapbox-pub/armada/tree/5b99f88d309052abc1eeb4f0b2ef437de086e709), especially its [NIP-17 protocol implementation](https://github.com/soapbox-pub/armada/blob/5b99f88d309052abc1eeb4f0b2ef437de086e709/src/lib/nip17/protocol.ts), [DM transport](https://github.com/soapbox-pub/armada/blob/5b99f88d309052abc1eeb4f0b2ef437de086e709/src/hooks/useDm17.ts), and [relay defaults](https://github.com/soapbox-pub/armada/blob/5b99f88d309052abc1eeb4f0b2ef437de086e709/src/lib/platform.ts); -- [OpenClaw `2026.6.1` at `2e08f0f`](https://github.com/openclaw/openclaw/tree/2e08f0f4221f522b60423ed6ffd83427942b28de), particularly its official Nostr channel, public plugin-SDK exports, package/setup contract, SecretRef implementation, persistent-dedupe helper, and channel-plugin guide as they existed at that revision; +- [OpenClaw `2026.6.34` at `5c38f99`](https://github.com/openclaw/openclaw/tree/v2026.6.34), particularly its official Nostr channel, public plugin-SDK exports, package/setup contract, SecretRef implementation, persistent-dedupe helper, and channel-plugin guide as they existed at that revision; - [NIP-17](https://github.com/nostr-protocol/nips/blob/master/17.md), [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md), [NIP-59](https://github.com/nostr-protocol/nips/blob/master/59.md), and [NIP-42](https://github.com/nostr-protocol/nips/blob/master/42.md). Important interoperability finding: Armada is the client, not one fixed messaging server. Its builds read and write NIP-17 DMs through configurable DM/app relays and discover a recipient's `kind:10050` inbox relays. The plugin defaults its own inbox to `wss://relay.armada.buzz`, `wss://relay.ditto.pub`, and `wss://relay.dreamith.to`; discovery defaults to Ditto and Dreamith. A recipient's valid `kind:10050` list is authoritative. It also publishes a separate self-addressed gift wrap for sender-side recovery. @@ -182,7 +182,7 @@ Crypto and relay code must not import OpenClaw agent/runtime internals. OpenClaw ### Reuse from `Ink-North/nostr-nip17-plugin` -Use the pinned Ink-North repository as the OpenClaw integration template, with the OpenClaw `2026.6.1` source and documentation taking precedence over legacy template fields: +Use the pinned Ink-North repository as the OpenClaw integration template, with the OpenClaw `2026.6.34` source and documentation taking precedence over legacy template fields: | Template area | Action in this repository | | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -196,13 +196,13 @@ Do not copy the template's NIP-04 path, multi-account behavior, permissive schem ### Reuse from `nostr-community-bot` -| Template area | Action in this repository | -| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `src/nip17-dm.ts` | Port the strict gift-wrap/seal/rumor validation and sanitized errors into `src/nip17.ts`. Extend automatic reply creation for recipient relay hints and sender self-copies. | -| `src/relay-connection-manager.ts` | Reuse the lifecycle model: concurrent connections, bounded exponential reconnect, subscription restoration, status snapshots, idempotent stop, and publish-to-at-least-one semantics. Split connection/auth details into `relay-session.ts`. | -| `src/bot.ts` replay handling | Reuse only rumor-age checks, bounded in-memory in-flight suppression, and stop-time dispatch guards. Replace its durable behavior with OpenClaw 2026.6.1's `createClaimableDedupe` persistent claim/commit/release helper, keyed by account and authenticated inner rumor ID. | -| `event-utils.ts` key parsing | Reuse the sanitized decoder and scalar validation, but expose only the file-resolved `nsec` input path in v1; raw hex private keys are rejected. Integrate it with OpenClaw `SecretInput` resolution. | -| Vitest suites | Port the positive/negative cryptographic vectors and relay lifecycle tests before implementation changes. | +| Template area | Action in this repository | +| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `src/nip17-dm.ts` | Port the strict gift-wrap/seal/rumor validation and sanitized errors into `src/nip17.ts`. Extend automatic reply creation for recipient relay hints and sender self-copies. | +| `src/relay-connection-manager.ts` | Reuse the lifecycle model: concurrent connections, bounded exponential reconnect, subscription restoration, status snapshots, idempotent stop, and publish-to-at-least-one semantics. Split connection/auth details into `relay-session.ts`. | +| `src/bot.ts` replay handling | Reuse only rumor-age checks, bounded in-memory in-flight suppression, and stop-time dispatch guards. Replace its durable behavior with OpenClaw 2026.6.34's `createClaimableDedupe` persistent claim/commit/release helper, keyed by account and authenticated inner rumor ID. | +| `event-utils.ts` key parsing | Reuse the sanitized decoder and scalar validation, but expose only the file-resolved `nsec` input path in v1; raw hex private keys are rejected. Integrate it with OpenClaw `SecretInput` resolution. | +| Vitest suites | Port the positive/negative cryptographic vectors and relay lifecycle tests before implementation changes. | ### Deliberately omit from `nostr-community-bot` @@ -212,7 +212,7 @@ Do not copy the template's NIP-04 path, multi-account behavior, permissive schem - any advertised community, group, or Armada Concord behavior; - publishing every reply blindly to only the configured relay set. -### Reuse from the OpenClaw 2026.6.1 channel SDK and bundled Nostr/Buzz plugins +### Reuse from the OpenClaw 2026.6.34 channel SDK and bundled Nostr/Buzz plugins Reuse patterns, not room behavior: @@ -235,11 +235,11 @@ Do not port Buzz room discovery, membership, directory groups, group allowlists, - `openclaw.setupEntry: "./dist/setup-entry.js"`; - channel metadata with ID `nostr`; - `openclaw.install.npmSpec: "openclaw-armada-dm"`, `minHostVersion: ">=2026.7.2-beta.6"`, and npm as the default remote choice if the package is ever published; -- `openclaw.compat.pluginApi: ">=2026.6.1"`; -- `openclaw.build.openclawVersion` and `openclaw.build.pluginSdkVersion` set to `2026.6.1`; +- `openclaw.compat.pluginApi: ">=2026.6.34"`; +- `openclaw.build.openclawVersion` and `openclaw.build.pluginSdkVersion` set to `2026.6.34`; - all runtime imports, including `nostr-tools`, declared in `dependencies`; OpenClaw remains a `peerDependency` and test/dev dependency. -`openclaw.plugin.json` must declare plugin ID `armada-dm`, `kind: "channel"`, channel `nostr`, an inline strict plugin-config schema, and the native-plugin metadata accepted by OpenClaw 2026.6.1. It must not declare the Ink-North template's legacy bundled-channel kind. The runtime channel schema remains the authority for `channels.nostr`; plugin-entry config is empty in single-account v1 and rejects unknown keys. +`openclaw.plugin.json` must declare plugin ID `armada-dm`, `kind: "channel"`, channel `nostr`, an inline strict plugin-config schema, and the native-plugin metadata accepted by OpenClaw 2026.6.34. It must not declare the Ink-North template's legacy bundled-channel kind. The runtime channel schema remains the authority for `channels.nostr`; plugin-entry config is empty in single-account v1 and rejects unknown keys. Published or packed artifacts must already contain built JavaScript. Installation must not depend on `postinstall`, `prepare`, TypeScript execution, network access, or lifecycle scripts because OpenClaw's managed npm installer ignores package scripts. @@ -252,18 +252,18 @@ The README must explain that `npm install --omit=dev` is only the contract for a Because `nostr` is a shared channel ID, installation must fail clearly if another enabled plugin already owns it. The migration guide must tell operators to disable/remove the previous `nostr-nip17` or bundled Nostr channel plugin while preserving `channels.nostr` and `secrets.providers.nostr`, then enable plugin ID `armada-dm`. Existing pairing approvals may remain on disk but are deliberately ignored by this plugin; installation must not delete them or broaden the configured owner. Contract tests must prove that ownership conflicts do not silently select one implementation. -### OpenClaw 2026.6.1 compatibility baseline +### OpenClaw 2026.6.34 compatibility baseline -OpenClaw `2026.6.1` at full commit `2e08f0f4221f522b60423ed6ffd83427942b28de` is the exact public-SDK baseline. Deployments require patched OpenClaw `2026.7.2-beta.6` or newer: +OpenClaw `2026.6.34` at full commit `5c38f996d4059ebd9080cf74dc611ec3a17f4d50` is the exact public-SDK baseline. Deployments require patched OpenClaw `2026.7.2-beta.6` or newer: -- compile and typecheck against exactly `openclaw@2026.6.1`, not a floating newer SDK; +- compile and typecheck against exactly `openclaw@2026.6.34`, not a floating newer SDK; - run package discovery, setup-entry import, SecretRef resolution, channel registration, single-owner ingress, reply delivery, status, and gateway lifecycle smoke tests against that exact host build; - use built JavaScript directly in `openclaw.extensions`/`openclaw.setupEntry`; do not emit the later `runtimeExtensions` or `runtimeSetupEntry` fields; - use `resolveStableChannelMessageIngress`, `dispatchInboundDirectDmWithRuntime`, and `createClaimableDedupe`, which are present in this revision; - do not import the later durable ingress monitor, ingress effect-once, or later-only setup/runtime helpers; - fail installation on hosts older than `2026.7.2-beta.6` through `openclaw.install.minHostVersion` and `peerDependencies`, while `openclaw.compat.pluginApi` records the narrower API surface used by the plugin. -CI must run an API-baseline test that imports every declared `openclaw/plugin-sdk/*` subpath from an installed `openclaw@2026.6.1` package. Documentation from `main` is informative only; the pinned source tree is authoritative for v1. +CI must run an API-baseline test that imports every declared `openclaw/plugin-sdk/*` subpath from an installed `openclaw@2026.6.34` package. Documentation from `main` is informative only; the pinned source tree is authoritative for v1. ## 8. Configuration contract @@ -354,7 +354,7 @@ Field behavior: Environment fallbacks may support only the non-secret `ARMADA_DM_RELAYS` and `ARMADA_DM_DISCOVERY_RELAYS` lists. The Nostr private key has no environment or inline fallback in v1. Secret values must never be copied into status objects, thrown errors, or logs. -The manifest's `channelConfigs.nostr.schema` must mirror the runtime Zod schema exactly and use `additionalProperties: false`. The plugin-entry `configSchema` is separately strict and empty for single-account v1. Set `peerDependencies.openclaw` to `>=2026.7.2-beta.6`, compile and typecheck against exactly `openclaw@2026.6.1`, and upgrade the baseline deliberately with contract tests. Do not import an SDK symbol merely because it exists in newer OpenClaw documentation. +The manifest's `channelConfigs.nostr.schema` must mirror the runtime Zod schema exactly and use `additionalProperties: false`. The plugin-entry `configSchema` is separately strict and empty for single-account v1. Set `peerDependencies.openclaw` to `>=2026.7.2-beta.6`, compile and typecheck against exactly `openclaw@2026.6.34`, and upgrade the baseline deliberately with contract tests. Do not import an SDK symbol merely because it exists in newer OpenClaw documentation. ### Relay URL and outbound-network policy @@ -447,7 +447,7 @@ Publication should reuse an active authenticated session when possible and open Deduplicate by authenticated inner rumor ID, not outer wrap ID. The same rumor can arrive through several relays or be rewrapped, and each copy must still produce only one agent turn. -OpenClaw 2026.6.1 does not expose the later durable ingress monitor/effect-once APIs to this plugin. Use its public `createClaimableDedupe` helper from `openclaw/plugin-sdk/persistent-dedupe` for logical replay protection, and rely on relay persistence plus the backdated subscription for crash recovery: +OpenClaw 2026.6.34 does not expose the later durable ingress monitor/effect-once APIs to this plugin. Use its public `createClaimableDedupe` helper from `openclaw/plugin-sdk/persistent-dedupe` for logical replay protection, and rely on relay persistence plus the backdated subscription for crash recovery: 1. At the single receive chokepoint, admit the bounded raw wrap to an account-scoped in-memory queue; a relay WebSocket has no acknowledgement/cursor that can be durably gated here. 2. Process the queue through bounded structural validation and decryption. @@ -456,7 +456,7 @@ OpenClaw 2026.6.1 does not expose the later durable ingress monitor/effect-once 5. Call `commit` only after the OpenClaw inbound dispatch returns successfully. Call `release` on validation/authorization/dispatch failure before success so relay redelivery can retry. 6. Configure the persistent JSON store in the OpenClaw-resolved plugin state directory with a TTL at least as long as `maxMessageAgeSeconds`, a bounded file entry count sized for the expected message rate, and the SDK's cross-process file lock. -Wrap `createClaimableDedupe` because its 2026.6.1 persistent implementation reports disk errors through `onDiskError` and otherwise falls back to memory. A disk error during `claim` must release/reject the event and stop new account dispatch until persistence is healthy. A disk error during post-dispatch `commit` cannot undo an already completed turn: retain in-memory suppression, mark the account degraded, stop intake, and surface a sanitized operator error. Never quietly continue normal operation with memory-only replay state. +Wrap `createClaimableDedupe` because its 2026.6.34 persistent implementation reports disk errors through `onDiskError` and otherwise falls back to memory. A disk error during `claim` must release/reject the event and stop new account dispatch until persistence is healthy. A disk error during post-dispatch `commit` cannot undo an already completed turn: retain in-memory suppression, mark the account degraded, stop intake, and surface a sanitized operator error. Never quietly continue normal operation with memory-only replay state. On restart, reconnect with the configured backdated `since`; conforming relays can redeliver stored gift wraps. This is relay-dependent recovery, not a local durable raw-event queue, and the limitation must be documented. The system does not claim mathematically exact-once agent side effects: a crash after agent/tool effects but before the dedupe commit can replay the turn. Acceptance guarantees one dispatch for ordinary cross-relay replay, rewrapping, reconnect, and same-process concurrency cases, while agent/tool permissions must assume this at-least-once crash edge. @@ -525,7 +525,7 @@ After cryptographic validation, resolve the OpenClaw route with: - reply target: canonical sender target; - reply-to ID: inbound rumor ID. -Run OpenClaw 2026.6.1's `resolveStableChannelMessageIngress` with channel ID `nostr`, account ID, a Nostr-pubkey `StableChannelIngressIdentityParams`, `useDefaultPairingStore: false`, the canonical sender subject/conversation, fixed `dmPolicy: "allowlist"`, the sole raw `allowFrom` owner, and command facts. Pass its sender and command decisions into `dispatchInboundDirectDmWithRuntime`; do not reconstruct authorization from message fields later. Use the bundled 2026.6.1 Nostr channel as the compile-time integration reference, while retaining this plan's stricter log redaction and NIP-17 authentication. +Run OpenClaw 2026.6.34's `resolveStableChannelMessageIngress` with channel ID `nostr`, account ID, a Nostr-pubkey `StableChannelIngressIdentityParams`, `useDefaultPairingStore: false`, the canonical sender subject/conversation, fixed `dmPolicy: "allowlist"`, the sole raw `allowFrom` owner, and command facts. Pass its sender and command decisions into `dispatchInboundDirectDmWithRuntime`; do not reconstruct authorization from message fields later. Use the bundled 2026.6.34 Nostr channel as the compile-time integration reference, while retaining this plan's stricter log redaction and NIP-17 authentication. The agent-facing body may label the sender with a short `npub`, but the stable ID remains hex. Do not fetch mutable profiles in v1. @@ -543,7 +543,7 @@ Return the inner rumor ID as `messageId`; outer wrap IDs are relay carriers and ## 13. Manual configuration and operator experience -The plugin has no interactive setup wizard. The operator provisions the dedicated secret file, configures the `nostr` single-value file provider, adds the matching `channels.nostr.privateKey` SecretRef and channel fields to `openclaw.json`, enables the plugin, reloads secrets when needed, and restarts the gateway. The minimal `setup-entry.ts` exists only because OpenClaw `2026.6.1` expects a separate import-safe package entry. +The plugin has no interactive setup wizard. The operator provisions the dedicated secret file, configures the `nostr` single-value file provider, adds the matching `channels.nostr.privateKey` SecretRef and channel fields to `openclaw.json`, enables the plugin, reloads secrets when needed, and restarts the gateway. The minimal `setup-entry.ts` exists only because OpenClaw `2026.6.34` expects a separate import-safe package entry. The plugin must never open the configured secret path directly. OpenClaw owns path expansion, file reads, ownership/permission checks, byte limits, trailing-newline removal, and SecretRef resolution. Runtime identity validation accepts only one resolved `nsec` encoding a non-zero secp256k1 scalar and must not accept or persist it through normal channel configuration, a command-line argument, an environment variable, status, or logs. @@ -578,8 +578,8 @@ Slices are sequential: an agent starts only after every dependency's exit gate i - Manifest recognizes exactly the `nostr` channel under plugin ID `armada-dm`. - Package name, install hint, plugin ID, channel ID, source entries, and built runtime entries are mutually consistent. -- Manifest uses `kind: "channel"`; package entries point directly to built JavaScript; compatibility/install/build metadata all name OpenClaw `2026.6.1`; later-only runtime-entry fields are absent. -- Every imported `openclaw/plugin-sdk/*` subpath resolves and typechecks from exactly `openclaw@2026.6.1`. +- Manifest uses `kind: "channel"`; package entries point directly to built JavaScript; compatibility/build metadata name the OpenClaw `2026.6.34` API baseline, install metadata names the patched `2026.7.2-beta.6` minimum host, and later-only runtime-entry fields are absent. +- Every imported `openclaw/plugin-sdk/*` subpath resolves and typechecks from exactly `openclaw@2026.6.34`. - Startup fails with a clear ownership diagnostic when another enabled plugin already registers channel `nostr`; migration preserves configuration but never silently replaces a runtime owner. - Runtime and JSON schemas accept the pre-provisioned `nostr` file provider and matching `channels.nostr.privateKey` SecretRef plus valid relay/DM-policy configuration. - Missing/mismatched providers, inline/env/exec secret inputs, file refs whose provider is not `nostr` or whose ID is not `value`, invalid protocols, empty relay sets, unknown keys, bad recovery/age/skew values, and invalid allowlist entries fail with sanitized errors. @@ -594,7 +594,7 @@ Slices are sequential: an agent starts only after every dependency's exit gate i **Exit** - `npm test`, `npm run lint`, `npm run build`, package validation, and `npm pack --dry-run` pass. -- `npm run audit` reports zero production and deploy-host vulnerabilities, checks the complete tree, and rejects every finding outside the explicitly isolated development-only `openclaw@2026.6.1` SDK baseline. +- `npm run audit` reports zero production and deploy-host vulnerabilities, checks the complete tree, and rejects every finding outside the explicitly isolated development-only `openclaw@2026.6.34` SDK baseline. - A clean npm-managed local patched OpenClaw host discovers the plugin after `npm install --omit=dev /absolute/path/to/openclaw-armada-dm`; a clean managed patched host also discovers the packed tarball through `npm-pack:`. - The migration smoke test disables the prior Nostr plugin, preserves `secrets.providers.nostr` and `channels.nostr`, configures exactly one owner, enables plugin `armada-dm`, audits/reloads secrets, restarts the gateway, and proves existing `nostr` pairing approvals are ignored rather than deleted or imported. @@ -648,7 +648,7 @@ Slices are sequential: an agent starts only after every dependency's exit gate i **Red** - Cross-relay duplicates and differently wrapped copies of one rumor cause one dispatch. -- Raw wraps enter a bounded in-memory queue; inner-rumor dedupe is claimed with OpenClaw 2026.6.1's `createClaimableDedupe` after authentication and committed only after successful dispatch. +- Raw wraps enter a bounded in-memory queue; inner-rumor dedupe is claimed with OpenClaw 2026.6.34's `createClaimableDedupe` after authentication and committed only after successful dispatch. - A failed dispatch releases the claim; a successful dispatch commits it; differently wrapped and concurrent copies cannot both dispatch during normal operation. - Dedupe disk failures stop account intake and surface a sanitized degraded state rather than silently continuing with memory-only replay protection. - Restart tests redeliver stored wraps through the loopback relay and exercise the documented crash window; no test asserts a later durable-ingress API or impossible absolute exactly-once side effects. @@ -661,7 +661,7 @@ Slices are sequential: an agent starts only after every dependency's exit gate i **Green** -- Implement the bounded receive queue, 2026.6.1 claimable-dedupe compatibility adapter, age/skew gate, `inbound.ts`, and gateway dispatch wiring. +- Implement the bounded receive queue, 2026.6.34 claimable-dedupe compatibility adapter, age/skew gate, `inbound.ts`, and gateway dispatch wiring. - Build the exact channel inbound context from the host ingress result. **Exit** @@ -721,7 +721,7 @@ Slices are sequential: an agent starts only after every dependency's exit gate i - Run a full encrypted round trip: disposable Armada-like sender -> relay -> plugin -> mocked OpenClaw dispatch -> encrypted reply -> sender decrypt. - Assert kind-1059 carrier events contain neither message plaintext nor the real sender pubkey outside encrypted layers. Separately assert and document that a relay receiving a NIP-42 AUTH event can observe the authenticating bot pubkey even though AUTH is not published as a stored DM event. - Assert package import, setup import, and disabled-channel discovery do not start background work. -- Run tests, coverage, lint, build, native package/manifest validation, the 2026.6.1 SDK-import baseline, both local-install smoke paths, package dry-run, package-content allowlist, and the complete-tree/zero-runtime-vulnerability audit in CI. +- Run tests, coverage, lint, build, native package/manifest validation, the 2026.6.34 SDK-import baseline, both local-install smoke paths, package dry-run, package-content allowlist, and the complete-tree/zero-runtime-vulnerability audit in CI. **Manual staging** @@ -737,7 +737,7 @@ Slices are sequential: an agent starts only after every dependency's exit gate i **Release** -- Pack an initial prerelease and test both local `npm install --omit=dev` and OpenClaw-managed `npm-pack:` installation against the exact `2026.6.1` API baseline and a deployable OpenClaw `2026.7.2-beta.6` or newer host. Registry publication is optional. +- Pack an initial prerelease and test both local `npm install --omit=dev` and OpenClaw-managed `npm-pack:` installation against the exact `2026.6.34` API baseline and a deployable OpenClaw `2026.7.2-beta.6` or newer host. Registry publication is optional. - Promote to `1.0.0` only after the current Armada client initiates a conversation, receives an automatic reply, and the bot safely recognizes its recovery copy. ## 15. Required documentation @@ -762,7 +762,7 @@ The README should include: The first release is complete when all of the following are true: - An npm-managed local OpenClaw checkout can discover the plugin after local `npm install --omit=dev`, and a clean standard OpenClaw installation can install the packed package through `npm-pack:`; both can configure, enable, disable, inspect, and remove it. -- All required manual configuration, secret, channel, single-owner ingress, reply-delivery, status, and lifecycle flows use only the OpenClaw `2026.6.1` (`2e08f0f`) public SDK surface, and the package advertises patched OpenClaw `2026.7.2-beta.6` as its minimum deployable host. +- All required manual configuration, secret, channel, single-owner ingress, reply-delivery, status, and lifecycle flows use only the OpenClaw `2026.6.34` public SDK surface, and the package advertises patched OpenClaw `2026.7.2-beta.6` as its minimum deployable host. - A pre-existing owner of channel `nostr` produces a clear conflict; migration to plugin `armada-dm` preserves the operator's `channels.nostr` and `secrets.providers.nostr` configuration only after the previous owner is disabled or removed. - The plugin exposes direct text chat and encrypted inbound-media capability only. - A valid Armada NIP-17 kind-14 DM reaches the intended OpenClaw agent once under cross-relay replay, rewrapping, reconnect, and concurrent-delivery tests; residual process-crash semantics are documented accurately rather than described as absolute exactly-once execution. diff --git a/docs/implementation-slices/01-installable-plugin-and-identity.md b/docs/implementation-slices/01-installable-plugin-and-identity.md index f66452e..56ea407 100644 --- a/docs/implementation-slices/01-installable-plugin-and-identity.md +++ b/docs/implementation-slices/01-installable-plugin-and-identity.md @@ -2,7 +2,7 @@ ## Agent brief -Implement only this slice. Read `docs/IMPLEMENTATION_PLAN.md` first and preserve its naming, security boundaries, and OpenClaw `2026.6.1` (`2e08f0f`) compatibility requirements. Use red-green-refactor: add a focused failing test, observe the failure, implement the smallest change, then run the focused and full suites. +Implement only this slice. Read `docs/IMPLEMENTATION_PLAN.md` first and preserve its naming, security boundaries, and OpenClaw `2026.6.34` compatibility requirements. Use red-green-refactor: add a focused failing test, observe the failure, implement the smallest change, then run the focused and full suites. ## Functional outcome @@ -14,7 +14,7 @@ This is an operator-facing slice. It does not yet exchange Nostr messages. - None. This is the first slice. - Use `Ink-North/nostr-nip17-plugin` only as the structural template described in the main plan. -- Treat the OpenClaw `2026.6.1` source and public SDK as authoritative. +- Treat the OpenClaw `2026.6.34` source and public SDK as authoritative. ## In scope @@ -23,7 +23,7 @@ This is an operator-facing slice. It does not yet exchange Nostr messages. - npm package `openclaw-armada-dm`; - plugin ID `armada-dm`; - channel ID `nostr`; - - exact plugin API baseline `2026.6.1` and minimum deployable host `2026.7.2-beta.6`. + - exact plugin API baseline `2026.6.34` and minimum deployable host `2026.7.2-beta.6`. - Add import-safe built runtime and setup entry points. - Register the single-account text-DM channel using only public SDK exports present at the pinned OpenClaw commit. - Add strict runtime and manifest schemas for `channels.nostr`. @@ -36,8 +36,8 @@ This is an operator-facing slice. It does not yet exchange Nostr messages. ## Required tests - Manifest and package metadata agree on all identifiers and built entry paths. -- `openclaw.plugin.json` uses the native `kind: "channel"` shape accepted by OpenClaw `2026.6.1` and rejects unknown plugin config. -- Every `openclaw/plugin-sdk/*` import resolves against exactly `openclaw@2026.6.1`. +- `openclaw.plugin.json` uses the native `kind: "channel"` shape accepted by OpenClaw `2026.6.34` and rejects unknown plugin config. +- Every `openclaw/plugin-sdk/*` import resolves against exactly `openclaw@2026.6.34`. - Importing package/setup entries and discovering a disabled channel starts no socket, timer, or crypto transport. - Valid relay, policy, limit, and SecretRef configuration parses. - Missing/mismatched providers, wrong SecretRef provider/ID, inline/env/exec secrets, invalid relay schemes, empty relay sets, unknown keys, invalid limits, and malformed allowlist entries fail with sanitized errors. diff --git a/docs/implementation-slices/04-allowlisted-ai-roundtrip.md b/docs/implementation-slices/04-allowlisted-ai-roundtrip.md index f5e50db..3a708e9 100644 --- a/docs/implementation-slices/04-allowlisted-ai-roundtrip.md +++ b/docs/implementation-slices/04-allowlisted-ai-roundtrip.md @@ -26,7 +26,7 @@ With `dmPolicy: "allowlist"` and the operator's user `npub` in `allowFrom`: - Implement the bounded inbound queue and `inbound.ts` mapping. - Authenticate and authorize exclusively with the verified inner rumor author. - Normalize configured allowlist entries to hex pubkeys. -- Integrate the exact OpenClaw `2026.6.1` APIs: +- Integrate the exact OpenClaw `2026.6.34` APIs: - `resolveStableChannelMessageIngress`; - `dispatchInboundDirectDmWithRuntime`; - stable direct-session identity; @@ -63,14 +63,14 @@ With `dmPolicy: "allowlist"` and the operator's user `npub` in `allowFrom`: ## Deliverables - Inbound authorization/dispatch adapter. -- Claimable-dedupe compatibility adapter for OpenClaw `2026.6.1`. +- Claimable-dedupe compatibility adapter for OpenClaw `2026.6.34`. - Recipient relay discovery/routing module with SSRF and DNS-rebinding defenses. - Automatic reply adapter and full encrypted loopback integration test. - A concise manual recipe using an allowlisted disposable user npub. ## Exit gate -- The complete encrypted request/AI-response path typechecks against the exact OpenClaw `2026.6.1` SDK baseline and passes on the patched deployable host with a mocked model response. +- The complete encrypted request/AI-response path typechecks against the exact OpenClaw `2026.6.34` SDK baseline and passes on the patched deployable host with a mocked model response. - Two different allowlisted senders receive independent direct sessions. - A user without a valid kind-10050 gets a clear delivery failure; the plugin does not silently publish to Ditto/Dreamith. - All earlier slice tests remain green. diff --git a/docs/implementation-slices/05-pairing-and-dm-policies.md b/docs/implementation-slices/05-pairing-and-dm-policies.md index 65f1c98..bccf89b 100644 --- a/docs/implementation-slices/05-pairing-and-dm-policies.md +++ b/docs/implementation-slices/05-pairing-and-dm-policies.md @@ -42,7 +42,7 @@ The operator configures exactly one owner `npub` or hex public key in `allowFrom - Configuration accepts one normalized `npub`, hex, or `nostr:` public key. - Configuration rejects an empty allowlist, multiple entries, wildcard, malformed entries, and every policy other than `allowlist`. -- The authenticated configured owner reaches the exact OpenClaw 2026.6.1 ingress and direct-DM dispatcher surfaces. +- The authenticated configured owner reaches the exact OpenClaw 2026.6.34 ingress and direct-DM dispatcher surfaces. - A different authenticated inner sender causes zero model dispatches and receives no response. - The outer ephemeral wrapper author is never compared with `allowFrom`. - `useDefaultPairingStore` is false so stale OpenClaw pairing approvals cannot authorize another sender. diff --git a/docs/implementation-slices/07-replay-resilience-and-resource-limits.md b/docs/implementation-slices/07-replay-resilience-and-resource-limits.md index 70db900..c4908a5 100644 --- a/docs/implementation-slices/07-replay-resilience-and-resource-limits.md +++ b/docs/implementation-slices/07-replay-resilience-and-resource-limits.md @@ -33,7 +33,7 @@ The bot continues serving conversations when one relay fails, reconnects safely - Different valid wraps containing the same inner rumor cause one dispatch. - Concurrent copies cannot both pass the claim gate. - Failed dispatch releases its claim; retry can succeed. Successful dispatch commits and suppresses later delivery. -- Restart redelivery exercises the documented crash window and does not depend on APIs introduced after OpenClaw `2026.6.1`. +- Restart redelivery exercises the documented crash window and does not depend on APIs introduced after OpenClaw `2026.6.34`. - Dedupe disk errors stop intake and expose a sanitized degraded state. - Offline message inside `recoveryLookbackSeconds` is processed after restart; stale messages are rejected. - Future, stale, self-authored, malformed, unauthorized, and oversized messages consume bounded work and never reach the model. diff --git a/docs/implementation-slices/08-setup-interoperability-and-release.md b/docs/implementation-slices/08-setup-interoperability-and-release.md index 5a4745d..3d35100 100644 --- a/docs/implementation-slices/08-setup-interoperability-and-release.md +++ b/docs/implementation-slices/08-setup-interoperability-and-release.md @@ -2,11 +2,11 @@ ## Agent brief -Finish operator documentation, diagnostics, interoperability evidence, and release validation after all functional and resilience slices are green. There is no interactive setup wizard. Operators configure the file SecretRef and `channels.nostr` directly through OpenClaw configuration. Keep only the minimal import-safe setup entry required by the OpenClaw `2026.6.1` package contract. +Finish operator documentation, diagnostics, interoperability evidence, and release validation after all functional and resilience slices are green. There is no interactive setup wizard. Operators configure the file SecretRef and `channels.nostr` directly through OpenClaw configuration. Keep only the minimal import-safe setup entry required by the OpenClaw `2026.6.34` package contract. ## Functional outcome -An operator who provisioned `/path/to/.openclaw/secrets/nostr_nsec`, installed the package on OpenClaw `2026.7.2-beta.6` or newer, and added the documented `secrets.providers.nostr` and `channels.nostr` configuration can restart the gateway, see a truthful sanitized probe, and hold a multi-turn encrypted conversation with the bot from the current Armada client. With `publishInbox: true`, gateway startup publishes and verifies the bot's kind-10050 inbox automatically. The package continues to use only the OpenClaw `2026.6.1` (`2e08f0f`) public SDK baseline. +An operator who provisioned `/path/to/.openclaw/secrets/nostr_nsec`, installed the package on OpenClaw `2026.7.2-beta.6` or newer, and added the documented `secrets.providers.nostr` and `channels.nostr` configuration can restart the gateway, see a truthful sanitized probe, and hold a multi-turn encrypted conversation with the bot from the current Armada client. With `publishInbox: true`, gateway startup publishes and verifies the bot's kind-10050 inbox automatically. The package continues to use only the OpenClaw `2026.6.34` public SDK baseline. ## Dependencies @@ -36,7 +36,7 @@ An operator who provisioned `/path/to/.openclaw/secrets/nostr_nsec`, installed t - The minimal setup entry and runtime package entries import without sockets, timers, configuration mutation, secret access, or transport startup. - `publishInbox: true` publishes and verifies the configured Armada/Ditto/Dreamith kind-10050 tags during gateway startup; failure remains visible and prevents ready status. - Status distinguishes invalid configuration/identity, unreachable relays, AUTH state, subscription state, missing inbox announcement, dedupe degradation, queue drops, authenticated rate limiting, partial relay operation, and healthy operation without payloads or relationship metadata. -- CI runs the full tests, coverage, lint, typecheck, format check, build, manifest/package validation, package dry-run, package-content allowlist, exact `2026.6.1` SDK-import baseline, built-artifact smoke test, and complete-tree/zero-runtime-vulnerability audit. +- CI runs the full tests, coverage, lint, typecheck, format check, build, manifest/package validation, package dry-run, package-content allowlist, exact `2026.6.34` SDK-import baseline, built-artifact smoke test, and complete-tree/zero-runtime-vulnerability audit. - A built-artifact test imports emitted JavaScript and proves an Armada-compatible NIP-17 request/reply encryption round trip without importing TypeScript source modules. ## Manual Armada staging diff --git a/docs/implementation-slices/10-nip17-encrypted-media-ingress.md b/docs/implementation-slices/10-nip17-encrypted-media-ingress.md index a2bc1dd..e025382 100644 --- a/docs/implementation-slices/10-nip17-encrypted-media-ingress.md +++ b/docs/implementation-slices/10-nip17-encrypted-media-ingress.md @@ -11,7 +11,7 @@ An owner can attach an image, audio recording, video, PDF, or other OpenClaw-sup ## Dependencies - Slices 01–09 complete and green. -- OpenClaw public plugin SDK exactly `2026.6.1`. +- OpenClaw public plugin SDK exactly `2026.6.34`. - NIP-17 kind-15 file-message format. - Armada client interoperability at `soapbox-pub/armada` commit `5b99f88d309052abc1eeb4f0b2ef437de086e709`. diff --git a/package-lock.json b/package-lock.json index 32bda1c..ce95f40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "openclaw-armada-dm", - "version": "0.1.1", + "version": "0.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "openclaw-armada-dm", - "version": "0.1.1", + "version": "0.1.2", "license": "MIT", "dependencies": { "nostr-tools": "2.25.0", @@ -19,7 +19,7 @@ "@types/ws": "8.18.1", "@vitest/coverage-v8": "4.1.11", "eslint": "10.9.1", - "openclaw": "2026.6.1", + "openclaw": "2026.6.34", "openclaw-host": "npm:openclaw@2026.7.2-beta.6", "prettier": "3.9.6", "typescript": "6.0.3", @@ -4438,9 +4438,9 @@ } }, "node_modules/openclaw": { - "version": "2026.6.1", - "resolved": "https://registry.npmjs.org/openclaw/-/openclaw-2026.6.1.tgz", - "integrity": "sha512-rGSwhIo8N37cQQ5puG8vmWZESE8q/ych5VFpzOQNcf49TF/rvCYyxiNAyot11qbUZF5wfLh8bsvofapnOEh0BQ==", + "version": "2026.6.34", + "resolved": "https://registry.npmjs.org/openclaw/-/openclaw-2026.6.34.tgz", + "integrity": "sha512-Rm4khBrWn9HYqE99NBryCFgjwlsIuwBqK5jIANn2773CGXJ1JIZkDn5twEHB+8SVFdh0FPNPHRVgZepzNJDfHg==", "dev": true, "hasInstallScript": true, "hasShrinkwrap": true, @@ -4466,7 +4466,6 @@ "clawpdf": "0.3.0", "commander": "14.0.3", "croner": "10.0.1", - "cross-spawn": "7.0.6", "diff": "9.0.0", "dotenv": "17.4.2", "express": "5.2.1", @@ -4490,12 +4489,12 @@ "qrcode": "1.5.4", "quickjs-wasi": "3.0.0", "rastermill": "0.3.1", - "tar": "7.5.15", + "tar": "7.5.20", "tree-sitter-bash": "0.25.1", "tslog": "4.10.2", "typebox": "1.1.39", "typescript": "6.0.3", - "undici": "8.3.0", + "undici": "8.9.0", "web-push": "3.6.7", "web-tree-sitter": "0.26.9", "ws": "8.21.0", @@ -6034,6 +6033,72 @@ "undici": ">=8.3.0 <9" } }, + "node_modules/openclaw/node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/openclaw/node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/openclaw/node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/openclaw/node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/openclaw/node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/openclaw/node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/openclaw/node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/openclaw/node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/openclaw/node_modules/@protobufjs/utf8": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/openclaw/node_modules/@silvia-odwyer/photon-node": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/@silvia-odwyer/photon-node/-/photon-node-0.3.4.tgz", @@ -6073,6 +6138,16 @@ "dev": true, "license": "MIT" }, + "node_modules/openclaw/node_modules/@types/node": { + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, "node_modules/openclaw/node_modules/@types/retry": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.5.tgz", @@ -6279,16 +6354,16 @@ "license": "MIT" }, "node_modules/openclaw/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/openclaw/node_modules/buffer-equal-constant-time": { @@ -6988,9 +7063,9 @@ } }, "node_modules/openclaw/node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-4.1.2.tgz", + "integrity": "sha512-TyGmBcbDTZXcb2cj5MV89DrF42DKvb3y5DDUNh95iO+IMeAzMkVSxK1PZRrRIpc9yg8U2GhGdbofNa0LS/a4Bw==", "dev": true, "funding": [ { @@ -7137,9 +7212,9 @@ } }, "node_modules/openclaw/node_modules/gaxios": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz", - "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.5.tgz", + "integrity": "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -7247,9 +7322,9 @@ } }, "node_modules/openclaw/node_modules/google-auth-library": { - "version": "10.6.2", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz", - "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==", + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.7.0.tgz", + "integrity": "sha512-QpTAbNJ36TliZLx3TTtahR8HG0hN9RllL1e3FymOvQSIKK8JmgV58H924ub2wa2DsS3ANjjP1Aw1N+Ramc8hqQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -7368,9 +7443,9 @@ } }, "node_modules/openclaw/node_modules/hono": { - "version": "4.12.18", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.18.tgz", - "integrity": "sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==", + "version": "4.12.25", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.25.tgz", + "integrity": "sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ==", "dev": true, "license": "MIT", "engines": { @@ -7538,9 +7613,9 @@ "license": "ISC" }, "node_modules/openclaw/node_modules/ip-address": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", - "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.3.1.tgz", + "integrity": "sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==", "dev": true, "license": "MIT", "engines": { @@ -8252,13 +8327,23 @@ } }, "node_modules/openclaw/node_modules/protobufjs": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.4.0.tgz", - "integrity": "sha512-iriNhQ57SYA5Jbdi+41AyPdx6jPPkFO7DODzkOBmqFhgYn/JzX2HxgxYPY18eQAs3CP/AWqtPvkWn8rclRAxdQ==", + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", "dev": true, "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", "long": "^5.3.2" }, "engines": { @@ -8920,9 +9005,9 @@ } }, "node_modules/openclaw/node_modules/tar": { - "version": "7.5.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.15.tgz", - "integrity": "sha512-dzGK0boVlC4W5QFuQN1EFSl3bIDYsk7Tj40U6eIBnK2k/8ml7TZ5agbI5j5+qnoVcAA+rNtBml8SEiLxZpNqRQ==", + "version": "7.5.20", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.20.tgz", + "integrity": "sha512-9FcyK4PA6+WbzlTM9WhQm6vB5W7cP7dUiPsv1g7YDwEQnQ1CGpK3MGlKk/ITVWMk05kHZuBhmVhiv8LZoy/PFQ==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -9094,15 +9179,22 @@ } }, "node_modules/openclaw/node_modules/undici": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.3.0.tgz", - "integrity": "sha512-TkUDgb6tl7KOGZ+7e8E3d2FYgUQgF6z5YypqjWmixVQSQERFcVrVg0ySADm2LVLRh5ljAaHTCR5Fmz3Q34rB7Q==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.9.0.tgz", + "integrity": "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==", "dev": true, "license": "MIT", "engines": { "node": ">=22.19.0" } }, + "node_modules/openclaw/node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT" + }, "node_modules/openclaw/node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -9624,9 +9716,9 @@ "license": "MIT" }, "node_modules/protobufjs": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", - "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz", + "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==", "dev": true, "hasInstallScript": true, "license": "BSD-3-Clause", diff --git a/package.json b/package.json index b5c9eed..52c207f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openclaw-armada-dm", - "version": "0.1.1", + "version": "0.1.2", "description": "OpenClaw channel plugin for private Armada NIP-17 direct messages", "type": "module", "main": "./dist/index.js", @@ -43,7 +43,7 @@ "@types/ws": "8.18.1", "@vitest/coverage-v8": "4.1.11", "eslint": "10.9.1", - "openclaw": "2026.6.1", + "openclaw": "2026.6.34", "openclaw-host": "npm:openclaw@2026.7.2-beta.6", "prettier": "3.9.6", "typescript": "6.0.3", @@ -75,11 +75,11 @@ "minHostVersion": ">=2026.7.2-beta.6" }, "compat": { - "pluginApi": ">=2026.6.1" + "pluginApi": ">=2026.6.34" }, "build": { - "openclawVersion": "2026.6.1", - "pluginSdkVersion": "2026.6.1" + "openclawVersion": "2026.6.34", + "pluginSdkVersion": "2026.6.34" } } } diff --git a/scripts/validate-host-security.mjs b/scripts/validate-host-security.mjs index 4c034ef..15ee95b 100644 --- a/scripts/validate-host-security.mjs +++ b/scripts/validate-host-security.mjs @@ -10,7 +10,7 @@ const lock = JSON.parse( await readFile(new URL("../package-lock.json", import.meta.url), "utf8"), ); -const sdkBaseline = "2026.6.1"; +const sdkBaseline = "2026.6.34"; const secureHostVersion = "2026.7.2-beta.6"; const minimumSecureHost = `>=${secureHostVersion}`; if ( @@ -87,7 +87,7 @@ if (unexpected.length > 0) { } console.log( - `Validated zero production/deploy-host vulnerabilities. The development-only OpenClaw ${sdkBaseline} SDK baseline has ${baselineCount} explicitly isolated audit findings.`, + `Validated zero production/deploy-host vulnerabilities. The development-only OpenClaw ${sdkBaseline} SDK tree has ${baselineCount} explicitly isolated audit findings.`, ); function getVulnerabilityCount(report) { diff --git a/scripts/validate-sdk-imports.mjs b/scripts/validate-sdk-imports.mjs index f86600c..46c5aa8 100644 --- a/scripts/validate-sdk-imports.mjs +++ b/scripts/validate-sdk-imports.mjs @@ -1,7 +1,7 @@ import { readFile } from "node:fs/promises"; import { URL } from "node:url"; -const BASELINE = "2026.6.1"; +const BASELINE = "2026.6.34"; const SUBPATHS = [ "openclaw/plugin-sdk/core", "openclaw/plugin-sdk/json-schema-runtime", diff --git a/src/__tests__/documentation.test.ts b/src/__tests__/documentation.test.ts index 77acad9..e58b4f9 100644 --- a/src/__tests__/documentation.test.ts +++ b/src/__tests__/documentation.test.ts @@ -15,6 +15,14 @@ describe("manual configuration documentation", () => { ); }); + it("uses the current package version in release commands", async () => { + const readme = await readFile(new URL("README.md", root), "utf8"); + + expect(readme).toContain("openclaw-armada-dm-0.1.2.tgz"); + expect(readme).toContain('git tag -a v0.1.2 -m "v0.1.2"'); + expect(readme).not.toContain("0.1.1"); + }); + it("documents openclaw.json configuration without requiring a wizard", async () => { const readme = await readFile(new URL("README.md", root), "utf8"); const slice = await readFile( diff --git a/src/__tests__/metadata.test.ts b/src/__tests__/metadata.test.ts index a3c69da..76c6919 100644 --- a/src/__tests__/metadata.test.ts +++ b/src/__tests__/metadata.test.ts @@ -19,6 +19,7 @@ describe("package and manifest contracts", () => { const channel = metadata.channel as Record; expect(pkg.name).toBe("openclaw-armada-dm"); + expect(pkg.version).toBe("0.1.2"); expect(manifest.id).toBe("armada-dm"); expect(manifest.kind).toBe("channel"); expect(manifest.channels).toEqual(["nostr"]); @@ -27,16 +28,16 @@ describe("package and manifest contracts", () => { expect(metadata.setupEntry).toBe("./dist/setup-entry.js"); expect(metadata).not.toHaveProperty("runtimeExtensions"); expect(metadata).not.toHaveProperty("runtimeSetupEntry"); - expect(metadata.compat).toEqual({ pluginApi: ">=2026.6.1" }); + expect(metadata.compat).toEqual({ pluginApi: ">=2026.6.34" }); expect(metadata.install).toMatchObject({ minHostVersion: ">=2026.7.2-beta.6", }); expect(metadata.build).toEqual({ - openclawVersion: "2026.6.1", - pluginSdkVersion: "2026.6.1", + openclawVersion: "2026.6.34", + pluginSdkVersion: "2026.6.34", }); expect((pkg.devDependencies as Record).openclaw).toBe( - "2026.6.1", + "2026.6.34", ); expect( (pkg.devDependencies as Record)["openclaw-host"], diff --git a/src/constants.ts b/src/constants.ts index 8691057..29c008c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,7 +1,7 @@ export const PLUGIN_ID = "armada-dm"; export const CHANNEL_ID = "nostr"; export const DEFAULT_ACCOUNT_ID = "default"; -export const OPENCLAW_BASELINE_VERSION = "2026.6.1"; +export const OPENCLAW_BASELINE_VERSION = "2026.6.34"; export const DEFAULT_INBOX_RELAYS = [ "wss://relay.armada.buzz/",