From 85d41cd2548094d935d6110353b16b5e76b261bf Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 6 Apr 2026 00:23:03 +0100 Subject: [PATCH] docs: document channel persisted auth metadata --- docs/plugins/manifest.md | 43 ++++++++++++++++----- src/plugins/bundled-plugin-metadata.test.ts | 8 ++++ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/docs/plugins/manifest.md b/docs/plugins/manifest.md index dc8b3a31d81..f8d4856388a 100644 --- a/docs/plugins/manifest.md +++ b/docs/plugins/manifest.md @@ -335,16 +335,17 @@ Some pre-runtime plugin metadata intentionally lives in `package.json` under the Important examples: -| Field | What it means | -| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -| `openclaw.extensions` | Declares native plugin entrypoints. | -| `openclaw.setupEntry` | Lightweight setup-only entrypoint used during onboarding and deferred channel startup. | -| `openclaw.channel` | Cheap channel catalog metadata like labels, docs paths, aliases, and selection copy. | -| `openclaw.install.npmSpec` / `openclaw.install.localPath` | Install/update hints for bundled and externally published plugins. | -| `openclaw.install.defaultChoice` | Preferred install path when multiple install sources are available. | -| `openclaw.install.minHostVersion` | Minimum supported OpenClaw host version, using a semver floor like `>=2026.3.22`. | -| `openclaw.install.allowInvalidConfigRecovery` | Allows a narrow bundled-plugin reinstall recovery path when config is invalid. | -| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | Lets setup-only channel surfaces load before the full channel plugin during startup. | +| Field | What it means | +| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| `openclaw.extensions` | Declares native plugin entrypoints. | +| `openclaw.setupEntry` | Lightweight setup-only entrypoint used during onboarding and deferred channel startup. | +| `openclaw.channel` | Cheap channel catalog metadata like labels, docs paths, aliases, and selection copy. | +| `openclaw.channel.persistedAuthState` | Lightweight persisted-auth checker metadata that can answer "is anything already signed in?" without loading the full channel runtime. | +| `openclaw.install.npmSpec` / `openclaw.install.localPath` | Install/update hints for bundled and externally published plugins. | +| `openclaw.install.defaultChoice` | Preferred install path when multiple install sources are available. | +| `openclaw.install.minHostVersion` | Minimum supported OpenClaw host version, using a semver floor like `>=2026.3.22`. | +| `openclaw.install.allowInvalidConfigRecovery` | Allows a narrow bundled-plugin reinstall recovery path when config is invalid. | +| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | Lets setup-only channel surfaces load before the full channel plugin during startup. | `openclaw.install.minHostVersion` is enforced during install and manifest registry loading. Invalid values are rejected; newer-but-valid values skip the @@ -357,6 +358,28 @@ missing bundled plugin path or a stale `channels.` entry for that same bundled plugin. Unrelated config errors still block install and send operators to `openclaw doctor --fix`. +`openclaw.channel.persistedAuthState` is package metadata for a tiny checker +module: + +```json +{ + "openclaw": { + "channel": { + "id": "whatsapp", + "persistedAuthState": { + "specifier": "./auth-presence", + "exportName": "hasAnyWhatsAppAuth" + } + } + } +} +``` + +Use it when setup, doctor, or configured-state flows need a cheap yes/no auth +probe before the full channel plugin loads. The target export should be a small +function that reads persisted state only; do not route it through the full +channel runtime barrel. + ## JSON Schema requirements - **Every plugin must ship a JSON Schema**, even if it accepts no config. diff --git a/src/plugins/bundled-plugin-metadata.test.ts b/src/plugins/bundled-plugin-metadata.test.ts index 7f7a0dd99e8..970aa258deb 100644 --- a/src/plugins/bundled-plugin-metadata.test.ts +++ b/src/plugins/bundled-plugin-metadata.test.ts @@ -99,6 +99,14 @@ describe("bundled plugin metadata", () => { ); }); + it("keeps bundled persisted-auth metadata on channel package manifests", () => { + const whatsapp = listBundledPluginMetadata().find((entry) => entry.dirName === "whatsapp"); + expect(whatsapp?.packageManifest?.channel?.persistedAuthState).toEqual({ + specifier: "./auth-presence", + exportName: "hasAnyWhatsAppAuth", + }); + }); + it("excludes test-only public surface artifacts", () => { listBundledPluginMetadata().forEach((entry) => expectTestOnlyArtifactsExcluded(entry.publicSurfaceArtifacts ?? []),