Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- First-time device auth no longer triggers a brief gateway restart after the token is captured. The plugin now registers `reload.noopPrefixes` for `plugins.entries.openclaw-security-advisor.config.authToken`, so the SecretRef patch written to `openclaw.json` after device auth is classified as a noop by the gateway reload planner instead of falling through to the default `plugins.* → restart` rule. The security checkup report is returned in the same response with no connection interruption. Scope is intentionally limited to the `authToken` field — `apiBaseUrl` and other config changes still take effect via the normal restart path.
- Release workflow: consolidated post-publish git/GitHub operations into a single atomic step with retries, eliminating a race condition where the version bump commit and tag could be pushed separately. Registry verification is now informational-only and never blocks tag/release steps.
- Release workflow: added a `Reconcile latest dist-tag` step that automatically repoints `npm dist-tags.latest` back to the highest stable version after a dev publish, preventing npm's first-publish auto-assign behavior from routing plain `npm install` users to a prerelease.

Expand Down
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,6 @@ connection. Then run `/security-checkup` again. The plugin will pick
up the approval, persist your auth token, run the checkup, and return
the report in the same response.

> **Note:** after the token is saved, OpenClaw briefly reloads to apply
> the new credential. You'll see a short connection blip in the chat
> UI. This is expected and only happens on first auth. Subsequent
> checkups run instantly without any reload.

For every run after the first, no auth prompt appears. The saved token
is reused automatically.

Expand Down
20 changes: 20 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,26 @@ export default definePluginEntry({
name: "OpenClaw Security Advisor",
description:
"Run a security checkup of your OpenClaw instance and get an expert analysis report from KiloCode.",
// The gateway reload planner classifies any change under `plugins.*`
// as `kind: "restart"` by default. writeStoredToken() patches
// plugins.entries.openclaw-security-advisor.config.authToken with a
// SecretRef after device auth, which would force a full gateway
// restart on first-time token capture. Plugin-registered reload
// rules are evaluated before the base rules (first-match wins), so
// declaring just the authToken path as a noop shadows the base
// restart rule for that one field without affecting anything else.
//
// Scope is intentionally narrow — only `.config.authToken`, NOT the
// full `.config` subtree. `apiBaseUrl` is captured as a snapshot in
// register() (see `pluginConfig` below), so runtime updates to it
// still need to fall through to the base `plugins.* → restart` rule
// to take effect. The plugin reads the token directly from disk via
// readTokenFromFile() on every invocation, so authToken noop is safe.
reload: {
noopPrefixes: [
"plugins.entries.openclaw-security-advisor.config.authToken",
],
},
// The SDK's OpenClawPluginApi type is large and internal. We narrow
// to our own structural PluginApi (declared above) immediately on
// entry so everything inside this function is strongly typed.
Expand Down
15 changes: 12 additions & 3 deletions src/auth/token-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,18 @@ async function ensureSecretsDir(): Promise<void> {
* 2. Register a file-based SecretRef provider in config
* 3. Point the plugin authToken config at that provider
*
* This triggers one gateway restart. On restart, OpenClaw resolves the
* SecretRef → api.pluginConfig.authToken = the token string, available
* in the plugin closure forever after.
* The config write does NOT trigger a gateway restart: the plugin
* declares `reload.noopPrefixes` for
* `plugins.entries.<id>.config.authToken` in index.ts, which shadows
* the gateway reload planner's default `plugins.* → restart` rule for
* just that one field. Other `.config.*` fields (e.g. `apiBaseUrl`)
* intentionally still hit the default restart rule so runtime edits
* take effect. The plugin reads the token directly from the secrets
* file via readTokenFromFile() on every invocation, so no hot-resolve
* of api.pluginConfig.authToken is needed — the SecretRef in
* openclaw.json exists for discoverability (so operators inspecting
* config can see where the token lives) and to align with openclaw's
* SecretRef direction.
*/
export async function writeStoredToken(
api: TokenStoreApi,
Expand Down
15 changes: 15 additions & 0 deletions src/openclaw-sdk.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@
*/

declare module "openclaw/plugin-sdk/plugin-entry" {
/**
* Subset of the SDK's OpenClawPluginReloadRegistration. Entries here let a
* plugin override the gateway reload planner's default classification for
* specific config prefixes. First-match wins, and plugin-registered rules
* are evaluated before the base `plugins.* -> restart` rule, so declaring
* `plugins.entries.<id>.config` here overrides the base restart for our
* own config subtree.
*/
export type PluginReloadRegistration = {
restartPrefixes?: string[];
hotPrefixes?: string[];
noopPrefixes?: string[];
};

/**
* Register a plugin with the OpenClaw runtime. The `register` callback
* receives a runtime-provided plugin API object. The SDK's concrete
Expand All @@ -24,6 +38,7 @@ declare module "openclaw/plugin-sdk/plugin-entry" {
id: string;
name: string;
description: string;
reload?: PluginReloadRegistration;
register: (api: any) => void;
}): unknown;
}
Expand Down
Loading