@wrongstack/plugins 0.306.4 → 0.307.0
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/dist/gitignore-guard.js +1 -1
- package/dist/index.js +393 -376
- package/dist/notify-hub.js +13 -0
- package/dist/path-guard/glob.d.ts +32 -0
- package/dist/path-guard/index.d.ts +2 -44
- package/dist/path-guard/shell-targets.d.ts +40 -0
- package/dist/path-guard/tool-targets.d.ts +34 -0
- package/dist/path-guard.js +377 -373
- package/package.json +4 -4
package/dist/notify-hub.js
CHANGED
|
@@ -481,6 +481,19 @@ var plugin = {
|
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
483
|
state.eventUnsubscribers = [];
|
|
484
|
+
if (api.tools?.unregister) {
|
|
485
|
+
try {
|
|
486
|
+
api.tools.unregister("notify_send");
|
|
487
|
+
api.tools.unregister("notify_hub_status");
|
|
488
|
+
} catch {
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (api.notifier?.unregisterChannel) {
|
|
492
|
+
try {
|
|
493
|
+
api.notifier.unregisterChannel("webhook");
|
|
494
|
+
} catch {
|
|
495
|
+
}
|
|
496
|
+
}
|
|
484
497
|
const channelCounters = state.channel?.counters();
|
|
485
498
|
state.channel = null;
|
|
486
499
|
state.lastDelivery = null;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface WriteTarget {
|
|
2
|
+
path: string;
|
|
3
|
+
kind: 'file' | 'scope' | 'deletion-scope';
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Compile a glob pattern to a RegExp. Supports `**` (any depth),
|
|
7
|
+
* `*` (within one segment), and `?` (single char). Matching is done
|
|
8
|
+
* against forward-slash-normalized relative-ish paths, and a pattern
|
|
9
|
+
* without a slash matches the basename anywhere in the tree
|
|
10
|
+
* (`.env` matches `sub/dir/.env`).
|
|
11
|
+
*/
|
|
12
|
+
export declare function compilePathGlob(pattern: string): RegExp;
|
|
13
|
+
export declare function normalizePath(p: string): string;
|
|
14
|
+
export declare function isAbsolutePath(path: string): boolean;
|
|
15
|
+
export declare function resolveTargetPath(path: string, base?: string): string;
|
|
16
|
+
/** Convert an absolute runtime target back to the repository-relative glob vocabulary. */
|
|
17
|
+
export declare function relativeToInvocationCwd(path: string, invocationCwd?: string): string;
|
|
18
|
+
export declare function effectiveToolCwd(toolInputCwd: unknown, invocationCwd?: string): string | undefined;
|
|
19
|
+
export declare function matchesAny(path: string, patterns: RegExp[]): boolean;
|
|
20
|
+
/** A glob-valued writer target describes a scope, not one concrete path. */
|
|
21
|
+
export declare function isUnresolvedPathScope(path: string): boolean;
|
|
22
|
+
export declare function isRootPathScope(path: string): boolean;
|
|
23
|
+
/** A single list target without a file-like basename may denote a directory. */
|
|
24
|
+
export declare function isDirectoryAmbiguousPath(path: string): boolean;
|
|
25
|
+
export declare function hasConfiguredProtectedDescendant(path: string, patterns: string[]): boolean;
|
|
26
|
+
export declare function staticPrefix(pattern: string): string;
|
|
27
|
+
export declare function hasPartialSegmentWildcard(pattern: string): boolean;
|
|
28
|
+
export declare function globWitness(pattern: string): string;
|
|
29
|
+
export declare function scopesMayOverlap(left: string, right: string): boolean;
|
|
30
|
+
export declare function targetIntersectsPatterns(target: WriteTarget, patternTexts: string[], patterns: RegExp[]): boolean;
|
|
31
|
+
export declare function targetFullyAllowed(target: WriteTarget, allowTexts: string[], allowRes: RegExp[]): boolean;
|
|
32
|
+
//# sourceMappingURL=glob.d.ts.map
|
|
@@ -2,53 +2,11 @@
|
|
|
2
2
|
* path-guard plugin — blocks (or warns about) writes, edits, and
|
|
3
3
|
* destructive shell commands that touch protected paths.
|
|
4
4
|
*
|
|
5
|
-
* `branch-guard` protects git *branches*; this plugin protects
|
|
6
|
-
* *files and directories*. A `PreToolUse` hook matches the target path
|
|
7
|
-
* against a configurable glob list:
|
|
8
|
-
*
|
|
9
|
-
* - any tool that declares `fs.write` (or, absent a capability list,
|
|
10
|
-
* `mutating: true`) → the `path` / `file_path` / `output_path` / …
|
|
11
|
-
* input field
|
|
12
|
-
* - shell commands → destructive ones only (`rm`, `rmdir`, `mv`, `cp`,
|
|
13
|
-
* `install`, `tee`, `dd of=`, output redirection `>` / `>>`, `truncate`)
|
|
14
|
-
* whose arguments mention a protected path
|
|
15
|
-
*
|
|
16
|
-
* The hook is registered for `*` and decides from the tool's own
|
|
17
|
-
* declaration. It used to be registered for `write|edit|bash|exec` and to
|
|
18
|
-
* branch on those four names, which meant `patch`, `scaffold`, every
|
|
19
|
-
* plugin-registered writer and every MCP filesystem server wrote past it
|
|
20
|
-
* untouched.
|
|
21
|
-
*
|
|
22
|
-
* Default protected set: lockfiles, `.env*` secrets, `.git/`
|
|
23
|
-
* internals, and production migration folders — files an agent
|
|
24
|
-
* should virtually never rewrite by hand.
|
|
25
|
-
*
|
|
26
|
-
* Config (`config.extensions['path-guard']`):
|
|
27
|
-
*
|
|
28
|
-
* ```jsonc
|
|
29
|
-
* {
|
|
30
|
-
* "enabled": true,
|
|
31
|
-
* "mode": "block", // "block" | "warn"
|
|
32
|
-
* "protect": ["pnpm-lock.yaml", ".env*", ".git/**", "**/migrations/**"],
|
|
33
|
-
* "allow": [] // globs that override protect
|
|
34
|
-
* }
|
|
35
|
-
* ```
|
|
36
|
-
*
|
|
37
|
-
* Toggle off with `{ "name": "path-guard", "enabled": false }` in
|
|
38
|
-
* `config.plugins`, or `"enabled": false` in the options above.
|
|
39
|
-
*
|
|
40
5
|
* @public
|
|
41
6
|
*/
|
|
42
7
|
import type { Plugin } from '@wrongstack/core/types';
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
* `*` (within one segment), and `?` (single char). Matching is done
|
|
46
|
-
* against forward-slash-normalized relative-ish paths, and a pattern
|
|
47
|
-
* without a slash matches the basename anywhere in the tree
|
|
48
|
-
* (`.env` matches `sub/dir/.env`).
|
|
49
|
-
*/
|
|
50
|
-
export declare function compilePathGlob(pattern: string): RegExp;
|
|
51
|
-
export declare function destructiveTargets(command: string): string[];
|
|
8
|
+
export { compilePathGlob } from './glob.js';
|
|
9
|
+
export { destructiveTargets } from './shell-targets.js';
|
|
52
10
|
declare const plugin: Plugin;
|
|
53
11
|
export default plugin;
|
|
54
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const VALUE_TAKING_GIT_OPTIONS: Set<string>;
|
|
2
|
+
export interface ShellToken {
|
|
3
|
+
value: string;
|
|
4
|
+
start: number;
|
|
5
|
+
end: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const MAX_LAUNCHER_TOKENS = 256;
|
|
8
|
+
export declare const MAX_LAUNCHER_LENGTH: number;
|
|
9
|
+
export declare function boundedShellTokens(raw: string): ShellToken[];
|
|
10
|
+
export declare function shellTokens(raw: string): string[];
|
|
11
|
+
export declare function gitInvocationArguments(command: string): string[];
|
|
12
|
+
export declare function gitSubcommandIndex(tokens: string[]): number;
|
|
13
|
+
export declare function commandDeletesImplicitScope(command: string): boolean;
|
|
14
|
+
export declare function normalizeEnvSplitPayload(payload: string): string;
|
|
15
|
+
export declare function unwrapEnvSplitStringAtBoundary(command: string): string;
|
|
16
|
+
export declare const SUDO_VALUE_TAKING: Set<string>;
|
|
17
|
+
export declare const ENV_VALUE_TAKING: Set<string>;
|
|
18
|
+
export declare const ENV_FLAG_OPTIONS: Set<string>;
|
|
19
|
+
export declare function stripTransparentLaunchers(command: string): string;
|
|
20
|
+
export declare function firstUnquotedShellSeparator(raw: string, start: number, end: number): number | undefined;
|
|
21
|
+
export declare function launcherPrefixLength(after: string, valueTaking: Set<string>, flagOptions?: Set<string>): number | undefined;
|
|
22
|
+
export declare function stripLauncherAtBoundary(command: string, launcher: 'env' | 'sudo', valueTaking: Set<string>): string;
|
|
23
|
+
export declare function commandRecursivelyDeletes(command: string): boolean;
|
|
24
|
+
export declare function quoteIsEscaped(command: string, index: number): boolean;
|
|
25
|
+
export declare function isQuoteBoundary(command: string, index: number, activeQuote: "'" | '"' | null): boolean;
|
|
26
|
+
export declare function executableCommandSubstitutions(command: string): string[];
|
|
27
|
+
export declare const MAX_DESTRUCTIVE_TARGET_DEPTH = 64;
|
|
28
|
+
export interface HeredocDelimiter {
|
|
29
|
+
delimiter: string;
|
|
30
|
+
start: number;
|
|
31
|
+
end: number;
|
|
32
|
+
quoted: boolean;
|
|
33
|
+
stripTabs: boolean;
|
|
34
|
+
}
|
|
35
|
+
export declare function heredocDelimiterOnLine(line: string): HeredocDelimiter | null;
|
|
36
|
+
export declare function commandSegmentBeforeHeredoc(prefix: string): string;
|
|
37
|
+
export declare function maskNonExecutingHeredocBodies(command: string): string;
|
|
38
|
+
export declare function destructiveTargets(command: string): string[];
|
|
39
|
+
export declare function destructiveTargetsAtDepth(command: string, depth: number): string[];
|
|
40
|
+
//# sourceMappingURL=shell-targets.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type WriteTarget } from './glob.js';
|
|
2
|
+
export declare const WRITE_CAPABILITIES: Set<string>;
|
|
3
|
+
export declare const DISK_MUTATING_CAPABILITIES: Set<string>;
|
|
4
|
+
export declare const SHELL_CAPABILITIES: Set<string>;
|
|
5
|
+
export declare const LEGACY_SHELL_TOOLS: Set<string>;
|
|
6
|
+
export declare const LEGACY_WRITE_TOOLS: Set<string>;
|
|
7
|
+
export declare const PATH_FIELDS: readonly ['path', 'file_path', 'filePath', 'target', 'target_path', 'targetPath', 'destination', 'dest', 'output_path', 'outputPath', 'out', 'file'];
|
|
8
|
+
export declare const PATH_LIST_FIELDS: readonly ['files', 'paths'];
|
|
9
|
+
export declare const SOURCE_PATH_FIELDS: readonly ['source', 'from', 'src', 'input_path', 'inputPath', 'old_path', 'oldPath'];
|
|
10
|
+
export declare const MOVE_TOOL_NAME: RegExp;
|
|
11
|
+
export declare const DIRECTORY_DELETE_TOOL_NAME: RegExp;
|
|
12
|
+
export declare function segmentedToolName(toolName: string): string;
|
|
13
|
+
export declare function isMoveToolName(toolName: string): boolean;
|
|
14
|
+
export declare function isDirectoryDeleteToolName(toolName: string): boolean;
|
|
15
|
+
export declare function cleanPatchPath(raw: string): string | null;
|
|
16
|
+
export declare function pathsFromPatch(patch: string): string[];
|
|
17
|
+
export declare function appendTarget(targets: WriteTarget[], value: unknown, kind: WriteTarget['kind'], base?: string): void;
|
|
18
|
+
export declare function appendTargetList(targets: WriteTarget[], value: unknown, directoryCapable: boolean, base?: string): void;
|
|
19
|
+
export declare function isReadOnlyInvocation(toolName: string, toolInput: Record<string, unknown>): boolean;
|
|
20
|
+
export declare function writesToDisk(input: {
|
|
21
|
+
toolName?: string | undefined;
|
|
22
|
+
toolInput?: Record<string, unknown> | undefined;
|
|
23
|
+
toolCapabilities?: readonly string[] | undefined;
|
|
24
|
+
toolMutating?: boolean | undefined;
|
|
25
|
+
}): boolean;
|
|
26
|
+
export declare function executesShell(input: {
|
|
27
|
+
toolName?: string | undefined;
|
|
28
|
+
toolInput?: Record<string, unknown> | undefined;
|
|
29
|
+
toolCapabilities?: readonly string[] | undefined;
|
|
30
|
+
toolMutating?: boolean | undefined;
|
|
31
|
+
}): boolean;
|
|
32
|
+
export declare function pathsFromToolInput(toolInput: Record<string, unknown>, toolName: string, invocationCwd?: string): WriteTarget[];
|
|
33
|
+
export declare function operationLabel(toolName: string): string;
|
|
34
|
+
//# sourceMappingURL=tool-targets.d.ts.map
|