dsh-permission-rules 0.2.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/CHANGELOG.md +50 -0
- package/LICENSE +201 -0
- package/README.es.md +182 -0
- package/README.hi.md +182 -0
- package/README.md +182 -0
- package/README.pt.md +182 -0
- package/README.zh.md +182 -0
- package/cordis.patch.yml +16 -0
- package/docs/rules-format.en.md +105 -0
- package/docs/rules-format.md +103 -0
- package/docs/rules-format.schema.json +117 -0
- package/lib/index.js +1606 -0
- package/lib/types/config.d.ts +83 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/config.js +72 -0
- package/lib/types/config.js.map +1 -0
- package/lib/types/events.d.ts +68 -0
- package/lib/types/events.d.ts.map +1 -0
- package/lib/types/events.js +21 -0
- package/lib/types/events.js.map +1 -0
- package/lib/types/glob.d.ts +55 -0
- package/lib/types/glob.d.ts.map +1 -0
- package/lib/types/glob.js +307 -0
- package/lib/types/glob.js.map +1 -0
- package/lib/types/index.d.ts +25 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +25 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/prose.d.ts +66 -0
- package/lib/types/prose.d.ts.map +1 -0
- package/lib/types/prose.js +143 -0
- package/lib/types/prose.js.map +1 -0
- package/lib/types/rules.d.ts +226 -0
- package/lib/types/rules.d.ts.map +1 -0
- package/lib/types/rules.js +581 -0
- package/lib/types/rules.js.map +1 -0
- package/lib/types/runtime.d.ts +175 -0
- package/lib/types/runtime.d.ts.map +1 -0
- package/lib/types/runtime.js +497 -0
- package/lib/types/runtime.js.map +1 -0
- package/package.json +103 -0
- package/scripts/repair-session-logs.mjs +327 -0
- package/src/config.ts +141 -0
- package/src/events.ts +75 -0
- package/src/glob.ts +303 -0
- package/src/index.ts +27 -0
- package/src/prose.ts +206 -0
- package/src/rules.ts +695 -0
- package/src/runtime.ts +504 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config schema and resolution for `dsh-permission-rules`. Every tunable is
|
|
3
|
+
* a validated {@link Config} field changeable from cordis.yml; the
|
|
4
|
+
* resolution step validates the numeric bounds and compiles nothing — rule
|
|
5
|
+
* files are external documents resolved per session cwd at load time.
|
|
6
|
+
* @module dsh-permission-rules/config
|
|
7
|
+
*/
|
|
8
|
+
import z from '@deepseek-ai/schemastery';
|
|
9
|
+
import type { PatternMode } from './rules.ts';
|
|
10
|
+
import type { UiLanguage } from './prose.ts';
|
|
11
|
+
/** What happens when a discovered rule file exists but cannot be parsed or compiled. */
|
|
12
|
+
export type BadFilePolicy = 'fail' | 'ignore-with-warning';
|
|
13
|
+
/** Which decisions are audit-logged: every call, or only rule hits. */
|
|
14
|
+
export type AuditGranularity = 'all' | 'hits';
|
|
15
|
+
/** Raw plugin config — every field optional; {@link Config} supplies the defaults. */
|
|
16
|
+
export interface Config {
|
|
17
|
+
/**
|
|
18
|
+
* Rule file location. A relative value is resolved against the calling
|
|
19
|
+
* session's workspace cwd (so `<cwd>/.dsh/rules.yaml` by default); an
|
|
20
|
+
* absolute value is used as-is for every session.
|
|
21
|
+
*/
|
|
22
|
+
rulesFile?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Fallback rule file used when per-cwd discovery finds no rule file.
|
|
25
|
+
* Absolute, or relative to `process.cwd()`. Unset = an empty rule set.
|
|
26
|
+
*/
|
|
27
|
+
fallbackPath?: string;
|
|
28
|
+
/**
|
|
29
|
+
* How an unreadable/invalid rule file is handled at load: `'fail'` throws
|
|
30
|
+
* (the pending tool call errors loudly; HMR reloads keep the previous
|
|
31
|
+
* rules and report the error), `'ignore-with-warning'` logs a warning and
|
|
32
|
+
* continues with an empty (initial) or previous (reload) rule set.
|
|
33
|
+
*/
|
|
34
|
+
badFilePolicy?: BadFilePolicy;
|
|
35
|
+
/** Hard cap on the number of rules across the effective source chain; a larger chain fails the load. */
|
|
36
|
+
maxRules?: number;
|
|
37
|
+
/** Hard cap on cached per-workspace rule loads; the least-recently-used workspace is evicted beyond it. */
|
|
38
|
+
maxCachedWorkspaces?: number;
|
|
39
|
+
/** How `params`, `paths`, and `when.env` patterns are interpreted: `'glob'` (default) or `'regex'`. */
|
|
40
|
+
patternMode?: PatternMode;
|
|
41
|
+
/** Whether the loaded rule file is watched and reloaded on change. */
|
|
42
|
+
watch?: boolean;
|
|
43
|
+
/** Debounce window for watch-driven reloads, in milliseconds. */
|
|
44
|
+
watchStabilityThresholdMs?: number;
|
|
45
|
+
/** Language of the `/rules` command output: `'en'` (default), `'zh'`, `'es'`, `'pt'`, or `'hi'`. */
|
|
46
|
+
language?: UiLanguage;
|
|
47
|
+
/** Whether `paths` patterns (and workspace-root comparison) ignore ASCII case; defaults to `true` on Windows. */
|
|
48
|
+
caseInsensitivePaths?: boolean;
|
|
49
|
+
/** Audit granularity: `'all'` logs every hit AND passthrough; `'hits'` skips passthrough events. */
|
|
50
|
+
audit?: AuditGranularity;
|
|
51
|
+
/** Walk parent directories of the session cwd and merge every found rule file (nearest first). */
|
|
52
|
+
searchUp?: boolean;
|
|
53
|
+
/** Hard cap on unbounded `*`/`**` quantifiers per glob pattern (backtracking-degree bound). */
|
|
54
|
+
maxGlobStars?: number;
|
|
55
|
+
}
|
|
56
|
+
/** Config after {@link resolveConfig}: every optional field has its explicit default. */
|
|
57
|
+
export interface ResolvedConfig {
|
|
58
|
+
readonly rulesFile: string;
|
|
59
|
+
readonly fallbackPath: string | undefined;
|
|
60
|
+
readonly badFilePolicy: BadFilePolicy;
|
|
61
|
+
readonly maxRules: number;
|
|
62
|
+
readonly maxCachedWorkspaces: number;
|
|
63
|
+
readonly patternMode: PatternMode;
|
|
64
|
+
readonly watch: boolean;
|
|
65
|
+
readonly watchStabilityThresholdMs: number;
|
|
66
|
+
readonly language: UiLanguage;
|
|
67
|
+
readonly caseInsensitivePaths: boolean;
|
|
68
|
+
readonly audit: AuditGranularity;
|
|
69
|
+
readonly searchUp: boolean;
|
|
70
|
+
readonly maxGlobStars: number;
|
|
71
|
+
}
|
|
72
|
+
/** Schemastery schema: the loader validates and fills defaults before `apply`. */
|
|
73
|
+
export declare const Config: z<Config>;
|
|
74
|
+
/**
|
|
75
|
+
* Validate raw values and fill explicit defaults. A `maxRules`,
|
|
76
|
+
* `maxCachedWorkspaces`, or `maxGlobStars` that is not a positive safe
|
|
77
|
+
* integer, a non-positive stability window, or `searchUp` combined with an
|
|
78
|
+
* absolute `rulesFile` throws here — misconfiguration fails loud at mount.
|
|
79
|
+
* @param config - raw (possibly partial) plugin config.
|
|
80
|
+
* @returns the fully resolved config.
|
|
81
|
+
*/
|
|
82
|
+
export declare function resolveConfig(config?: Config): ResolvedConfig;
|
|
83
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,CAAC,MAAM,0BAA0B,CAAA;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,wFAAwF;AACxF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,qBAAqB,CAAA;AAE1D,uEAAuE;AACvE,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,MAAM,CAAA;AAE7C,sFAAsF;AACtF,MAAM,WAAW,MAAM;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,wGAAwG;IACxG,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2GAA2G;IAC3G,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,uGAAuG;IACvG,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,iEAAiE;IACjE,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,oGAAoG;IACpG,QAAQ,CAAC,EAAE,UAAU,CAAA;IACrB,iHAAiH;IACjH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,oGAAoG;IACpG,KAAK,CAAC,EAAE,gBAAgB,CAAA;IACxB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,+FAA+F;IAC/F,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,yFAAyF;AACzF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IACzC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAA;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAA;IACpC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAA;IAC1C,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAA;IAC7B,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAA;IACtC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAA;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC9B;AAED,kFAAkF;AAClF,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAc3B,CAAA;AAEF;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAW,GAAG,cAAc,CAqCjE"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config schema and resolution for `dsh-permission-rules`. Every tunable is
|
|
3
|
+
* a validated {@link Config} field changeable from cordis.yml; the
|
|
4
|
+
* resolution step validates the numeric bounds and compiles nothing — rule
|
|
5
|
+
* files are external documents resolved per session cwd at load time.
|
|
6
|
+
* @module dsh-permission-rules/config
|
|
7
|
+
*/
|
|
8
|
+
import { isAbsolute } from 'node:path';
|
|
9
|
+
import z from '@deepseek-ai/schemastery';
|
|
10
|
+
/** Schemastery schema: the loader validates and fills defaults before `apply`. */
|
|
11
|
+
export const Config = z.object({
|
|
12
|
+
rulesFile: z.string().default('.dsh/rules.yaml'),
|
|
13
|
+
fallbackPath: z.string(),
|
|
14
|
+
badFilePolicy: z.union(['fail', 'ignore-with-warning']).default('fail'),
|
|
15
|
+
maxRules: z.number().default(256),
|
|
16
|
+
maxCachedWorkspaces: z.number().default(512),
|
|
17
|
+
patternMode: z.union(['glob', 'regex']).default('glob'),
|
|
18
|
+
watch: z.boolean().default(true),
|
|
19
|
+
watchStabilityThresholdMs: z.number().default(200),
|
|
20
|
+
language: z.union(['en', 'zh', 'es', 'pt', 'hi']).default('en'),
|
|
21
|
+
caseInsensitivePaths: z.boolean().default(process.platform === 'win32'),
|
|
22
|
+
audit: z.union(['all', 'hits']).default('all'),
|
|
23
|
+
searchUp: z.boolean().default(false),
|
|
24
|
+
maxGlobStars: z.number().default(2),
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Validate raw values and fill explicit defaults. A `maxRules`,
|
|
28
|
+
* `maxCachedWorkspaces`, or `maxGlobStars` that is not a positive safe
|
|
29
|
+
* integer, a non-positive stability window, or `searchUp` combined with an
|
|
30
|
+
* absolute `rulesFile` throws here — misconfiguration fails loud at mount.
|
|
31
|
+
* @param config - raw (possibly partial) plugin config.
|
|
32
|
+
* @returns the fully resolved config.
|
|
33
|
+
*/
|
|
34
|
+
export function resolveConfig(config = {}) {
|
|
35
|
+
const rulesFile = config.rulesFile ?? '.dsh/rules.yaml';
|
|
36
|
+
const searchUp = config.searchUp ?? false;
|
|
37
|
+
if (searchUp && isAbsolute(rulesFile)) {
|
|
38
|
+
throw new TypeError(`searchUp cannot be combined with an absolute rulesFile (${JSON.stringify(rulesFile)}): parent-directory walking needs a relative file name`);
|
|
39
|
+
}
|
|
40
|
+
const maxRules = config.maxRules ?? 256;
|
|
41
|
+
if (!Number.isSafeInteger(maxRules) || maxRules <= 0) {
|
|
42
|
+
throw new TypeError(`maxRules must be a positive safe integer, got ${String(config.maxRules)}`);
|
|
43
|
+
}
|
|
44
|
+
const watchStabilityThresholdMs = config.watchStabilityThresholdMs ?? 200;
|
|
45
|
+
if (!Number.isSafeInteger(watchStabilityThresholdMs) || watchStabilityThresholdMs < 0) {
|
|
46
|
+
throw new TypeError(`watchStabilityThresholdMs must be a non-negative safe integer, got ${String(config.watchStabilityThresholdMs)}`);
|
|
47
|
+
}
|
|
48
|
+
const maxCachedWorkspaces = config.maxCachedWorkspaces ?? 512;
|
|
49
|
+
if (!Number.isSafeInteger(maxCachedWorkspaces) || maxCachedWorkspaces <= 0) {
|
|
50
|
+
throw new TypeError(`maxCachedWorkspaces must be a positive safe integer, got ${String(config.maxCachedWorkspaces)}`);
|
|
51
|
+
}
|
|
52
|
+
const maxGlobStars = config.maxGlobStars ?? 2;
|
|
53
|
+
if (!Number.isSafeInteger(maxGlobStars) || maxGlobStars <= 0) {
|
|
54
|
+
throw new TypeError(`maxGlobStars must be a positive safe integer, got ${String(config.maxGlobStars)}`);
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
rulesFile,
|
|
58
|
+
fallbackPath: config.fallbackPath,
|
|
59
|
+
badFilePolicy: config.badFilePolicy ?? 'fail',
|
|
60
|
+
maxRules,
|
|
61
|
+
maxCachedWorkspaces,
|
|
62
|
+
patternMode: config.patternMode ?? 'glob',
|
|
63
|
+
watch: config.watch ?? true,
|
|
64
|
+
watchStabilityThresholdMs,
|
|
65
|
+
language: config.language ?? 'en',
|
|
66
|
+
caseInsensitivePaths: config.caseInsensitivePaths ?? process.platform === 'win32',
|
|
67
|
+
audit: config.audit ?? 'all',
|
|
68
|
+
searchUp,
|
|
69
|
+
maxGlobStars,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable session vocabulary for `dsh-permission-rules`: the
|
|
3
|
+
* `permissionRules/decision` audit event, appended for every hit AND every
|
|
4
|
+
* passthrough. Log-only — it never enters the model transcript; the only
|
|
5
|
+
* model-visible plugin content is the deny/ask reason the tools registry
|
|
6
|
+
* materializes into the denied tool result, which carries the same
|
|
7
|
+
* `callId`, keeping model-visible ⟺ logged reconstructable.
|
|
8
|
+
*
|
|
9
|
+
* `outcome` records the FINAL pre-execute decision: on a deny/ask hit it
|
|
10
|
+
* equals `action` (the plugin short-circuits); on an allow hit or a
|
|
11
|
+
* passthrough it carries the downstream listeners' decision, so the audit
|
|
12
|
+
* never claims a call was allowed when a later listener denied it.
|
|
13
|
+
*
|
|
14
|
+
* The event is appended with the envelope's `ignorable: true` marker (see
|
|
15
|
+
* {@link AuditAppend}), so a harness build whose generated event vocabulary
|
|
16
|
+
* does not include this out-of-repo type still loads the log — it skips the
|
|
17
|
+
* audit record instead of refusing the whole session.
|
|
18
|
+
* @module dsh-permission-rules/events
|
|
19
|
+
*/
|
|
20
|
+
import type { CallId } from '@deepseek-ai/dsh-llm';
|
|
21
|
+
import type { PreToolDecision } from '@deepseek-ai/dsh-tools';
|
|
22
|
+
declare module '@deepseek-ai/dsh-session/types' {
|
|
23
|
+
interface SessionEventMap {
|
|
24
|
+
/**
|
|
25
|
+
* One permission-rules decision for a pending tool call — log-only
|
|
26
|
+
* audit (like `approval/asked`; NOT a surface event). `action` is
|
|
27
|
+
* `'allow' | 'deny' | 'ask' | 'passthrough'`; `ruleIndex` (0-based) and
|
|
28
|
+
* `reason` appear only on hits. `source` is the absolute rule file of
|
|
29
|
+
* the matched rule, or the nearest effective file on a passthrough, or
|
|
30
|
+
* `''` when no rule file was active. `outcome` is the final pre-execute
|
|
31
|
+
* decision the waterfall settled on.
|
|
32
|
+
*/
|
|
33
|
+
'permissionRules/decision': {
|
|
34
|
+
toolName: string;
|
|
35
|
+
callId?: CallId;
|
|
36
|
+
source: string;
|
|
37
|
+
action: 'allow' | 'deny' | 'ask' | 'passthrough';
|
|
38
|
+
outcome?: 'allow' | 'deny' | 'ask';
|
|
39
|
+
ruleIndex?: number;
|
|
40
|
+
reason?: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Every action a decision event can carry. */
|
|
45
|
+
export type DecisionAction = 'allow' | 'deny' | 'ask' | 'passthrough';
|
|
46
|
+
/** The final pre-execute decision kinds a host can settle on. */
|
|
47
|
+
export type DecisionOutcome = PreToolDecision['kind'];
|
|
48
|
+
/** The payload of one `permissionRules/decision` audit record. */
|
|
49
|
+
export interface AuditDecision {
|
|
50
|
+
toolName: string;
|
|
51
|
+
callId?: CallId;
|
|
52
|
+
source: string;
|
|
53
|
+
action: DecisionAction;
|
|
54
|
+
outcome?: DecisionOutcome;
|
|
55
|
+
ruleIndex?: number;
|
|
56
|
+
reason?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* `Session.append` narrowed to this plugin's audit event. The options bag
|
|
60
|
+
* exists only on host builds that expose the `ignorable` envelope-marker
|
|
61
|
+
* surface (post-rc.6 `@deepseek-ai/dsh-session`); an rc.6 host accepts and
|
|
62
|
+
* ignores the third argument, appending the identical event without the
|
|
63
|
+
* marker — no behavior change, no failure either way.
|
|
64
|
+
*/
|
|
65
|
+
export type AuditAppend = (type: 'permissionRules/decision', data: AuditDecision, options?: {
|
|
66
|
+
ignorable?: true;
|
|
67
|
+
}) => unknown;
|
|
68
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D,OAAO,QAAQ,gCAAgC,CAAC;IAC9C,UAAU,eAAe;QACvB;;;;;;;;WAQG;QACH,0BAA0B,EAAE;YAC1B,QAAQ,EAAE,MAAM,CAAA;YAChB,MAAM,CAAC,EAAE,MAAM,CAAA;YACf,MAAM,EAAE,MAAM,CAAA;YACd,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,aAAa,CAAA;YAChD,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAA;YAClC,SAAS,CAAC,EAAE,MAAM,CAAA;YAClB,MAAM,CAAC,EAAE,MAAM,CAAA;SAChB,CAAA;KACF;CACF;AAED,+CAA+C;AAC/C,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,aAAa,CAAA;AAErE,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;AAErD,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,cAAc,CAAA;IACtB,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,CACxB,IAAI,EAAE,0BAA0B,EAChC,IAAI,EAAE,aAAa,EACnB,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,IAAI,CAAA;CAAE,KAC3B,OAAO,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable session vocabulary for `dsh-permission-rules`: the
|
|
3
|
+
* `permissionRules/decision` audit event, appended for every hit AND every
|
|
4
|
+
* passthrough. Log-only — it never enters the model transcript; the only
|
|
5
|
+
* model-visible plugin content is the deny/ask reason the tools registry
|
|
6
|
+
* materializes into the denied tool result, which carries the same
|
|
7
|
+
* `callId`, keeping model-visible ⟺ logged reconstructable.
|
|
8
|
+
*
|
|
9
|
+
* `outcome` records the FINAL pre-execute decision: on a deny/ask hit it
|
|
10
|
+
* equals `action` (the plugin short-circuits); on an allow hit or a
|
|
11
|
+
* passthrough it carries the downstream listeners' decision, so the audit
|
|
12
|
+
* never claims a call was allowed when a later listener denied it.
|
|
13
|
+
*
|
|
14
|
+
* The event is appended with the envelope's `ignorable: true` marker (see
|
|
15
|
+
* {@link AuditAppend}), so a harness build whose generated event vocabulary
|
|
16
|
+
* does not include this out-of-repo type still loads the log — it skips the
|
|
17
|
+
* audit record instead of refusing the whole session.
|
|
18
|
+
* @module dsh-permission-rules/events
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict glob→RegExp compilation and regex-safety validation for rule
|
|
3
|
+
* patterns. A conservative, validated glob subset: `*` (within one path
|
|
4
|
+
* segment), `**` (any depth, including zero), `?` (one character),
|
|
5
|
+
* `[abc]` / `[!abc]` character classes, and `\x` escapes. Unbalanced
|
|
6
|
+
* brackets, empty classes, and trailing escapes throw at compile time — a
|
|
7
|
+
* bad glob must fail loudly at load, never silently match nothing at
|
|
8
|
+
* runtime.
|
|
9
|
+
*
|
|
10
|
+
* Catastrophic-backtracking defense, tuned per pattern flavor:
|
|
11
|
+
* - Glob output is fully machine-generated, so the backtracking degree is
|
|
12
|
+
* exactly the number of star expansions: each `*`/`**` emits exactly one
|
|
13
|
+
* unbounded quantifier and no group is ever emitted. {@link compileGlob}
|
|
14
|
+
* therefore caps that count via `maxStars`.
|
|
15
|
+
* - User regexes (patternMode `regex`) are scanned structurally: a
|
|
16
|
+
* quantifier applied to a group containing an unbounded quantifier, and a
|
|
17
|
+
* quantified group whose literal alternation branches overlap, are
|
|
18
|
+
* rejected at load. Chains of independent top-level quantifiers
|
|
19
|
+
* (`\d+\.\d+\.\d+`) stay allowed — a documented, deliberate limitation:
|
|
20
|
+
* regex mode is the escape hatch, glob mode is the guarded default.
|
|
21
|
+
* @module dsh-permission-rules/glob
|
|
22
|
+
*/
|
|
23
|
+
/** Raised by {@link compileGlob} on a syntactically invalid or over-quantified pattern. */
|
|
24
|
+
export declare class GlobError extends TypeError {
|
|
25
|
+
constructor(message: string);
|
|
26
|
+
}
|
|
27
|
+
/** Compile options for {@link compileGlob}. */
|
|
28
|
+
export interface GlobCompileOptions {
|
|
29
|
+
/** `true` keeps `*`/`?` inside one path segment (for `paths` patterns). */
|
|
30
|
+
readonly segments: boolean;
|
|
31
|
+
/** Compile with the `i` flag so matching ignores ASCII case. */
|
|
32
|
+
readonly caseInsensitive?: boolean;
|
|
33
|
+
/** Hard cap on unbounded star expansions; exceeding it throws. Unset = unlimited. */
|
|
34
|
+
readonly maxStars?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Compile one glob pattern to an anchored regular expression.
|
|
38
|
+
* @param pattern - the glob source.
|
|
39
|
+
* @param options - segment semantics, case handling, and the star cap.
|
|
40
|
+
* @returns a RegExp matching the whole candidate string.
|
|
41
|
+
* @throws {@link GlobError} on unbalanced `[`, empty classes, a trailing
|
|
42
|
+
* escape, or more star expansions than `options.maxStars` allows.
|
|
43
|
+
*/
|
|
44
|
+
export declare function compileGlob(pattern: string, options: GlobCompileOptions): RegExp;
|
|
45
|
+
/**
|
|
46
|
+
* Compile one pattern as an unanchored regex, rejecting syntax errors and
|
|
47
|
+
* catastrophic-backtracking structures loudly.
|
|
48
|
+
* @param pattern - the regex source.
|
|
49
|
+
* @returns the compiled RegExp.
|
|
50
|
+
* @throws TypeError when the pattern is invalid, nests an unbounded
|
|
51
|
+
* quantifier, or quantifies a group with overlapping literal alternation
|
|
52
|
+
* branches.
|
|
53
|
+
*/
|
|
54
|
+
export declare function compilePatternRegex(pattern: string): RegExp;
|
|
55
|
+
//# sourceMappingURL=glob.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../src/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,2FAA2F;AAC3F,qBAAa,SAAU,SAAQ,SAAS;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAClC,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAgEhF;AAOD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAS3D"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict glob→RegExp compilation and regex-safety validation for rule
|
|
3
|
+
* patterns. A conservative, validated glob subset: `*` (within one path
|
|
4
|
+
* segment), `**` (any depth, including zero), `?` (one character),
|
|
5
|
+
* `[abc]` / `[!abc]` character classes, and `\x` escapes. Unbalanced
|
|
6
|
+
* brackets, empty classes, and trailing escapes throw at compile time — a
|
|
7
|
+
* bad glob must fail loudly at load, never silently match nothing at
|
|
8
|
+
* runtime.
|
|
9
|
+
*
|
|
10
|
+
* Catastrophic-backtracking defense, tuned per pattern flavor:
|
|
11
|
+
* - Glob output is fully machine-generated, so the backtracking degree is
|
|
12
|
+
* exactly the number of star expansions: each `*`/`**` emits exactly one
|
|
13
|
+
* unbounded quantifier and no group is ever emitted. {@link compileGlob}
|
|
14
|
+
* therefore caps that count via `maxStars`.
|
|
15
|
+
* - User regexes (patternMode `regex`) are scanned structurally: a
|
|
16
|
+
* quantifier applied to a group containing an unbounded quantifier, and a
|
|
17
|
+
* quantified group whose literal alternation branches overlap, are
|
|
18
|
+
* rejected at load. Chains of independent top-level quantifiers
|
|
19
|
+
* (`\d+\.\d+\.\d+`) stay allowed — a documented, deliberate limitation:
|
|
20
|
+
* regex mode is the escape hatch, glob mode is the guarded default.
|
|
21
|
+
* @module dsh-permission-rules/glob
|
|
22
|
+
*/
|
|
23
|
+
/** Raised by {@link compileGlob} on a syntactically invalid or over-quantified pattern. */
|
|
24
|
+
export class GlobError extends TypeError {
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'GlobError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Compile one glob pattern to an anchored regular expression.
|
|
32
|
+
* @param pattern - the glob source.
|
|
33
|
+
* @param options - segment semantics, case handling, and the star cap.
|
|
34
|
+
* @returns a RegExp matching the whole candidate string.
|
|
35
|
+
* @throws {@link GlobError} on unbalanced `[`, empty classes, a trailing
|
|
36
|
+
* escape, or more star expansions than `options.maxStars` allows.
|
|
37
|
+
*/
|
|
38
|
+
export function compileGlob(pattern, options) {
|
|
39
|
+
let out = '';
|
|
40
|
+
let stars = 0;
|
|
41
|
+
let i = 0;
|
|
42
|
+
while (i < pattern.length) {
|
|
43
|
+
const ch = pattern[i];
|
|
44
|
+
if (ch === '\\') {
|
|
45
|
+
const next = pattern[i + 1];
|
|
46
|
+
if (next === undefined)
|
|
47
|
+
throw new GlobError(`glob ${JSON.stringify(pattern)} ends with a dangling escape`);
|
|
48
|
+
out += escapeRegExpChar(next);
|
|
49
|
+
i += 2;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (ch === '*') {
|
|
53
|
+
if (pattern[i + 1] === '*') {
|
|
54
|
+
// `**` crosses path segments. Collapse runs of `**` and any
|
|
55
|
+
// following separator into one zero-or-more-any-depth group, so
|
|
56
|
+
// `a/**/b`, `a/**b`, and `a/***/b` all behave the same.
|
|
57
|
+
out += '.*';
|
|
58
|
+
stars += 1;
|
|
59
|
+
i += 2;
|
|
60
|
+
while (pattern[i] === '*')
|
|
61
|
+
i += 1;
|
|
62
|
+
if (pattern[i] === '/')
|
|
63
|
+
i += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// A single star never crosses a path separator.
|
|
67
|
+
out += options.segments ? '[^/]*' : '.*';
|
|
68
|
+
stars += 1;
|
|
69
|
+
i += 1;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (ch === '?') {
|
|
73
|
+
out += options.segments ? '[^/]' : '.';
|
|
74
|
+
i += 1;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (ch === '[') {
|
|
78
|
+
const end = pattern.indexOf(']', i + 1);
|
|
79
|
+
if (end < 0)
|
|
80
|
+
throw new GlobError(`glob ${JSON.stringify(pattern)} has an unbalanced "["`);
|
|
81
|
+
const body = pattern.slice(i + 1, end);
|
|
82
|
+
if (body.length === 0)
|
|
83
|
+
throw new GlobError(`glob ${JSON.stringify(pattern)} has an empty character class`);
|
|
84
|
+
let content = body;
|
|
85
|
+
let negate = false;
|
|
86
|
+
if (content.startsWith('!')) {
|
|
87
|
+
negate = true;
|
|
88
|
+
content = content.slice(1);
|
|
89
|
+
}
|
|
90
|
+
if (content.length === 0)
|
|
91
|
+
throw new GlobError(`glob ${JSON.stringify(pattern)} has an empty character class`);
|
|
92
|
+
out += `[${negate ? '^' : ''}${content.replaceAll('\\', '\\\\')}]`;
|
|
93
|
+
i = end + 1;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (ch === ']')
|
|
97
|
+
throw new GlobError(`glob ${JSON.stringify(pattern)} has an unbalanced "]"`);
|
|
98
|
+
out += escapeRegExpChar(ch);
|
|
99
|
+
i += 1;
|
|
100
|
+
}
|
|
101
|
+
if (options.maxStars !== undefined && stars > options.maxStars) {
|
|
102
|
+
throw new GlobError(`glob ${JSON.stringify(pattern)} expands to ${stars} unbounded star quantifiers (max ${options.maxStars}); split it into several patterns`);
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
return new RegExp(`^${out}$`, options.caseInsensitive === true ? 'iu' : 'u');
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
throw new GlobError(`glob ${JSON.stringify(pattern)} compiles to an invalid regular expression: ${String(error)}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Escape one literal character for a RegExp source. */
|
|
112
|
+
function escapeRegExpChar(ch) {
|
|
113
|
+
return /[.*+?^${}()|[\]\\/]/.test(ch) ? `\\${ch}` : ch;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Compile one pattern as an unanchored regex, rejecting syntax errors and
|
|
117
|
+
* catastrophic-backtracking structures loudly.
|
|
118
|
+
* @param pattern - the regex source.
|
|
119
|
+
* @returns the compiled RegExp.
|
|
120
|
+
* @throws TypeError when the pattern is invalid, nests an unbounded
|
|
121
|
+
* quantifier, or quantifies a group with overlapping literal alternation
|
|
122
|
+
* branches.
|
|
123
|
+
*/
|
|
124
|
+
export function compilePatternRegex(pattern) {
|
|
125
|
+
let compiled;
|
|
126
|
+
try {
|
|
127
|
+
compiled = new RegExp(pattern, 'u');
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
throw new TypeError(`pattern ${JSON.stringify(pattern)} is not a valid regular expression: ${String(error)}`, { cause: error });
|
|
131
|
+
}
|
|
132
|
+
assertSafeRegexStructure(pattern);
|
|
133
|
+
return compiled;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Structural ReDoS scan. Rejects (a) an unbounded quantifier (`*`, `+`,
|
|
137
|
+
* `{m,}`) applied to a group whose body contains an unbounded quantifier,
|
|
138
|
+
* and (b) a quantified group whose fully-literal alternation branches
|
|
139
|
+
* overlap as prefixes. Everything else — including chains of independent
|
|
140
|
+
* top-level quantifiers — compiles untouched.
|
|
141
|
+
* @param pattern - the already-syntax-valid regex source.
|
|
142
|
+
* @throws TypeError on a rejected structure.
|
|
143
|
+
*/
|
|
144
|
+
function assertSafeRegexStructure(pattern) {
|
|
145
|
+
const stack = [];
|
|
146
|
+
let i = 0;
|
|
147
|
+
const markUnbounded = () => {
|
|
148
|
+
const top = stack[stack.length - 1];
|
|
149
|
+
if (top !== undefined)
|
|
150
|
+
top.unbounded = true;
|
|
151
|
+
};
|
|
152
|
+
const reject = (message) => {
|
|
153
|
+
throw new TypeError(`pattern ${JSON.stringify(pattern)} is rejected: ${message} risks catastrophic backtracking; restructure the pattern or use glob mode`);
|
|
154
|
+
};
|
|
155
|
+
while (i < pattern.length) {
|
|
156
|
+
const ch = pattern[i];
|
|
157
|
+
if (ch === '\\') {
|
|
158
|
+
i += 2;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (ch === '[') {
|
|
162
|
+
i += 1;
|
|
163
|
+
while (i < pattern.length && pattern[i] !== ']') {
|
|
164
|
+
if (pattern[i] === '\\')
|
|
165
|
+
i += 1;
|
|
166
|
+
i += 1;
|
|
167
|
+
}
|
|
168
|
+
i += 1;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (ch === '(') {
|
|
172
|
+
stack.push({ start: i, unbounded: false });
|
|
173
|
+
i += 1;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (ch === ')') {
|
|
177
|
+
const group = stack.pop();
|
|
178
|
+
// An unbalanced `)` is invalid syntax; the compile above already rejected it.
|
|
179
|
+
if (group === undefined) {
|
|
180
|
+
i += 1;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
const quantifier = quantifierAt(pattern, i + 1);
|
|
184
|
+
if (quantifier !== undefined) {
|
|
185
|
+
if (quantifier.unbounded) {
|
|
186
|
+
if (group.unbounded) {
|
|
187
|
+
reject(`quantifier ${quantifier.text} applies to a group containing an unbounded quantifier`);
|
|
188
|
+
}
|
|
189
|
+
if (hasAmbiguousAlternation(pattern, group.start + 1, i)) {
|
|
190
|
+
reject(`quantified group ${JSON.stringify(pattern.slice(group.start, quantifier.end + 1))} has overlapping alternation branches`);
|
|
191
|
+
}
|
|
192
|
+
markUnbounded();
|
|
193
|
+
}
|
|
194
|
+
i = quantifier.end + 1;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (group.unbounded)
|
|
198
|
+
markUnbounded();
|
|
199
|
+
i += 1;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (ch === '*' || ch === '+') {
|
|
203
|
+
markUnbounded();
|
|
204
|
+
i += 1;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (ch === '{') {
|
|
208
|
+
const parsed = parseBraceQuantifier(pattern, i);
|
|
209
|
+
if (parsed !== undefined) {
|
|
210
|
+
if (parsed.unbounded)
|
|
211
|
+
markUnbounded();
|
|
212
|
+
i = parsed.end + 1;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
// Not a quantifier (a `\p{L}`-style body is reached after its escape
|
|
216
|
+
// was skipped above): an ordinary literal.
|
|
217
|
+
i += 1;
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
// `?` is always bounded; literals, `.`, `|`, `^`, `$` pass through.
|
|
221
|
+
i += 1;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/** One parsed quantifier token, when the character at `index` starts one. */
|
|
225
|
+
function quantifierAt(pattern, index) {
|
|
226
|
+
const ch = pattern[index];
|
|
227
|
+
if (ch === '*' || ch === '+')
|
|
228
|
+
return { text: ch, end: index, unbounded: true };
|
|
229
|
+
if (ch === '?')
|
|
230
|
+
return { text: ch, end: index, unbounded: false };
|
|
231
|
+
if (ch === '{')
|
|
232
|
+
return parseBraceQuantifier(pattern, index);
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
/** Parse `{m}`, `{m,}`, or `{m,n}` at `start`; other braces are not quantifiers. */
|
|
236
|
+
function parseBraceQuantifier(pattern, start) {
|
|
237
|
+
const close = pattern.indexOf('}', start + 1);
|
|
238
|
+
if (close < 0)
|
|
239
|
+
return undefined;
|
|
240
|
+
const body = pattern.slice(start + 1, close);
|
|
241
|
+
if (!/^\d+(,\d*)?$/.test(body))
|
|
242
|
+
return undefined;
|
|
243
|
+
const unbounded = body.includes(',') && body.endsWith(',');
|
|
244
|
+
return { text: pattern.slice(start, close + 1), end: close, unbounded };
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Whether a group body (between the parens) contains a top-level
|
|
248
|
+
* alternation with two fully-literal branches where one is a prefix of the
|
|
249
|
+
* other — the `(a|aa)+` ambiguity that makes repetition exponential.
|
|
250
|
+
* @param pattern - the full pattern.
|
|
251
|
+
* @param start - index just after the group's `(`.
|
|
252
|
+
* @param end - index of the group's `)`.
|
|
253
|
+
* @returns true when such an overlap exists.
|
|
254
|
+
*/
|
|
255
|
+
function hasAmbiguousAlternation(pattern, start, end) {
|
|
256
|
+
const branches = [];
|
|
257
|
+
let depth = 0;
|
|
258
|
+
let branchStart = start;
|
|
259
|
+
let hasPipe = false;
|
|
260
|
+
for (let i = start; i < end; i += 1) {
|
|
261
|
+
const ch = pattern[i];
|
|
262
|
+
if (ch === '\\') {
|
|
263
|
+
i += 1;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (ch === '[') {
|
|
267
|
+
while (i < end && pattern[i] !== ']') {
|
|
268
|
+
if (pattern[i] === '\\')
|
|
269
|
+
i += 1;
|
|
270
|
+
i += 1;
|
|
271
|
+
}
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (ch === '(') {
|
|
275
|
+
depth += 1;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (ch === ')') {
|
|
279
|
+
depth -= 1;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (ch === '|' && depth === 0) {
|
|
283
|
+
hasPipe = true;
|
|
284
|
+
branches.push(pattern.slice(branchStart, i));
|
|
285
|
+
branchStart = i + 1;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (!hasPipe)
|
|
289
|
+
return false;
|
|
290
|
+
branches.push(pattern.slice(branchStart, end));
|
|
291
|
+
for (let a = 0; a < branches.length; a += 1) {
|
|
292
|
+
for (let b = a + 1; b < branches.length; b += 1) {
|
|
293
|
+
if (literalPrefixOf(branches[a], branches[b]))
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
/** True when two fully-literal branches share their complete shorter text as a prefix. */
|
|
300
|
+
function literalPrefixOf(x, y) {
|
|
301
|
+
const literal = /^[^*+?()|[\]{}^$.\\]+$/;
|
|
302
|
+
if (!literal.test(x) || !literal.test(y))
|
|
303
|
+
return false;
|
|
304
|
+
const min = Math.min(x.length, y.length);
|
|
305
|
+
return x.slice(0, min) === y.slice(0, min);
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=glob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/glob.ts"],"names":[],"mappings":"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"}
|