dsh-permission-rules 0.4.2 → 0.5.2

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.es.md +160 -117
  3. package/README.hi.md +162 -119
  4. package/README.md +133 -90
  5. package/README.pt.md +161 -118
  6. package/README.zh.md +162 -119
  7. package/docs/rule-test-vectors/README.md +28 -0
  8. package/docs/rule-test-vectors/corpus.json +109 -0
  9. package/lib/client.js +4693 -0
  10. package/lib/client.js.map +1 -0
  11. package/lib/index.js +1530 -179
  12. package/lib/typert.host.js +4305 -0
  13. package/lib/types/client/index.d.ts +28 -0
  14. package/lib/types/client/index.d.ts.map +1 -0
  15. package/lib/types/client/locales.d.ts +9 -0
  16. package/lib/types/client/locales.d.ts.map +1 -0
  17. package/lib/types/client/remote.d.ts +181 -0
  18. package/lib/types/client/remote.d.ts.map +1 -0
  19. package/lib/types/client/section.d.ts +35 -0
  20. package/lib/types/client/section.d.ts.map +1 -0
  21. package/lib/types/config.d.ts +54 -2
  22. package/lib/types/config.d.ts.map +1 -1
  23. package/lib/types/events.d.ts +45 -0
  24. package/lib/types/events.d.ts.map +1 -1
  25. package/lib/types/index.d.ts +8 -6
  26. package/lib/types/index.d.ts.map +1 -1
  27. package/lib/types/network.d.ts +90 -0
  28. package/lib/types/network.d.ts.map +1 -0
  29. package/lib/types/prose.d.ts +15 -0
  30. package/lib/types/prose.d.ts.map +1 -1
  31. package/lib/types/proxy.d.ts +128 -0
  32. package/lib/types/proxy.d.ts.map +1 -0
  33. package/lib/types/remote-service.d.ts +45 -0
  34. package/lib/types/remote-service.d.ts.map +1 -0
  35. package/lib/types/rules.d.ts +131 -0
  36. package/lib/types/rules.d.ts.map +1 -1
  37. package/lib/types/runtime.d.ts +153 -21
  38. package/lib/types/runtime.d.ts.map +1 -1
  39. package/lib/types/settings.d.ts +28 -0
  40. package/lib/types/settings.d.ts.map +1 -0
  41. package/lib/types/typert.host.d.ts +166 -0
  42. package/lib/types/typert.host.d.ts.map +1 -0
  43. package/lib/types/wire.d.ts +421 -0
  44. package/lib/types/wire.d.ts.map +1 -0
  45. package/package.json +182 -144
  46. package/scripts/repair-session-logs.mjs +7 -2
  47. package/src/client/index.ts +111 -0
  48. package/src/client/locales.ts +94 -0
  49. package/src/client/remote.ts +41 -0
  50. package/src/client/section.ts +201 -0
  51. package/src/config.ts +111 -0
  52. package/src/events.ts +46 -0
  53. package/src/index.ts +2 -0
  54. package/src/network.ts +177 -0
  55. package/src/prose.ts +85 -10
  56. package/src/proxy.ts +327 -0
  57. package/src/remote-service.ts +109 -0
  58. package/src/rules.ts +424 -5
  59. package/src/runtime.ts +464 -53
  60. package/src/settings.ts +74 -0
  61. package/src/typert.host.ts +25 -0
  62. package/src/wire.ts +239 -0
  63. package/lib/types/config.js +0 -99
  64. package/lib/types/config.js.map +0 -1
  65. package/lib/types/events.js +0 -44
  66. package/lib/types/events.js.map +0 -1
  67. package/lib/types/glob.js +0 -307
  68. package/lib/types/glob.js.map +0 -1
  69. package/lib/types/index.js +0 -27
  70. package/lib/types/index.js.map +0 -1
  71. package/lib/types/prose.js +0 -173
  72. package/lib/types/prose.js.map +0 -1
  73. package/lib/types/rules.js +0 -610
  74. package/lib/types/rules.js.map +0 -1
  75. package/lib/types/runtime.js +0 -818
  76. package/lib/types/runtime.js.map +0 -1
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Host-side settings-namespace wiring: registers the whole plugin config
3
+ * as the `permission-rules` settings section (editable from the Web
4
+ * settings surface, loopback-only), keeps the runtime's config source
5
+ * pointed at the resolved section, and rebinds the network proxy when a
6
+ * bind/env-relevant knob changes live. On hosts without a settings
7
+ * service (the rc.6 line) nothing registers and the composition entry
8
+ * keeps serving the config — the plugin stays fully functional.
9
+ *
10
+ * The registration uses only structural interfaces: `@deepseek-ai/
11
+ * dsh-settings` is not an rc.6 peer, so importing it would hard-fail
12
+ * older hosts; the real service satisfies these shapes.
13
+ * @module dsh-permission-rules/settings
14
+ */
15
+
16
+ import type { Context } from '@deepseek-ai/cordis'
17
+ import type z from '@deepseek-ai/schemastery'
18
+ import { Config, resolveConfig } from './config.ts'
19
+ import type { Config as PluginConfig, ResolvedConfig } from './config.ts'
20
+ import type { PermissionRulesRuntime } from './runtime.ts'
21
+
22
+ /** The settings namespace this plugin owns (kebab-case, per the provider contract). */
23
+ export const SETTINGS_NAMESPACE = 'permission-rules'
24
+
25
+ /** The owner-facing scope the real settings service hands back. */
26
+ interface SettingsScopeLike<T> {
27
+ get(): T
28
+ watch(callback: (next: T, prev: T) => void | Promise<void>): () => void
29
+ }
30
+
31
+ /** The structural settings-provider shape the real `ctx.settings` satisfies. */
32
+ interface SettingsProviderLike {
33
+ register<T>(ns: string, schema: z<T>, options?: {
34
+ base?: Partial<T>
35
+ expose?: boolean
36
+ applies?: string
37
+ validate?: (value: T) => void
38
+ }): SettingsScopeLike<T>
39
+ }
40
+
41
+ /**
42
+ * Register the settings section and bind the runtime's live config
43
+ * source. Runs only where a settings service is composed.
44
+ * @param ctx - the plugin context.
45
+ * @param runtime - the runtime whose config source follows the section.
46
+ * @param entry - the composition entry config (the section's `base` layer).
47
+ */
48
+ export function attachSettingsSection(ctx: Context, runtime: PermissionRulesRuntime, entry: PluginConfig): void {
49
+ ctx.inject(['settings'], (scope) => {
50
+ const settings = scope.get('settings') as SettingsProviderLike | undefined
51
+ if (settings === undefined) return
52
+ const registration = settings.register<PluginConfig>(SETTINGS_NAMESPACE, Config as z<PluginConfig>, {
53
+ base: entry,
54
+ expose: true,
55
+ applies: 'live',
56
+ validate: (value: PluginConfig) => {
57
+ // Schemastery already enforced the closed enums; this re-runs the
58
+ // numeric-bounds checks so an out-of-range stored value is refused
59
+ // at write time instead of disabling the owner later.
60
+ resolveConfig(value)
61
+ },
62
+ })
63
+ runtime.setConfigSource(() => resolveConfig(registration.get()))
64
+ registration.watch((next, prev) => {
65
+ const nextConfig = resolveConfig(next) as ResolvedConfig
66
+ const prevConfig = resolveConfig(prev) as ResolvedConfig
67
+ const rebind = nextConfig.network.proxyPort !== prevConfig.network.proxyPort
68
+ || nextConfig.network.proxyBind !== prevConfig.network.proxyBind
69
+ || nextConfig.network.injectEnv !== prevConfig.network.injectEnv
70
+ || nextConfig.network.noProxy !== prevConfig.network.noProxy
71
+ if (rebind) void runtime.onNetworkConfigChanged()
72
+ })
73
+ })
74
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The hand-written Typert HOST manifest for `dsh-permission-rules`,
3
+ * exported as `./typert` so the harness's typert-loader registers the
4
+ * `permissionRules` settings-page invocations automatically when this
5
+ * plugin mounts. Same shape as a generator output (validated by the
6
+ * loader): package face, empty model and schemas, and the canonical
7
+ * invocation list shared with the client Remote contribution
8
+ * (`src/wire.ts`).
9
+ * @module dsh-permission-rules/typert
10
+ */
11
+
12
+ import { PERMISSION_RULES_INVOCATIONS } from './wire.ts'
13
+
14
+ /** Host Typert manifest (validated by `@deepseek-ai/dsh-typert-loader`). */
15
+ export const TYPERT = Object.freeze({
16
+ package: 'dsh-permission-rules',
17
+ face: 'host',
18
+ schemas: Object.freeze([]),
19
+ invocations: PERMISSION_RULES_INVOCATIONS,
20
+ model: Object.freeze({
21
+ services: Object.freeze([]),
22
+ events: Object.freeze([]),
23
+ objects: Object.freeze([]),
24
+ }),
25
+ })
package/src/wire.ts ADDED
@@ -0,0 +1,239 @@
1
+ /**
2
+ * The settings-page wire vocabulary: the snapshot/rule-editor types served
3
+ * over the `permissionRules` Typert Remote namespace, their zod v4
4
+ * validation schemas (the strict codec both Typert faces carry), and the
5
+ * invocation descriptors shared verbatim by the host `./typert` manifest
6
+ * and the client Remote contribution. One canonical source for both faces
7
+ * keeps the host and client codecs from ever drifting apart.
8
+ * @module dsh-permission-rules/wire
9
+ */
10
+
11
+ import { z } from 'zod'
12
+ import type { InvocationDescriptor } from '@deepseek-ai/dsh-typert-protocol'
13
+
14
+ /** The three network policy modes (wire vocabulary). */
15
+ export type NetworkModeWire = 'deny-all' | 'whitelist' | 'allow-all'
16
+
17
+ /** One recent proxy-layer block, sanitized for display. */
18
+ export interface NetworkBlockView {
19
+ /** Epoch ms of the block. */
20
+ time: number
21
+ /** Attributed shell tool (`bash`/`pwsh`) or `subprocess`. */
22
+ tool: string
23
+ /** Whether an in-flight shell execution could be named. */
24
+ attributed: boolean
25
+ /** Blocked target host. */
26
+ domain: string
27
+ scheme: 'http' | 'https' | null
28
+ port: number | null
29
+ action: 'deny' | 'ask'
30
+ mode: NetworkModeWire
31
+ /** Whether a rule (true) or the mode default (false) blocked the target. */
32
+ matched: boolean
33
+ source: string
34
+ ruleIndex: number | null
35
+ reason: string | null
36
+ }
37
+
38
+ /** One rule file the editor may read/write (a known rule source only). */
39
+ export interface RuleSourceView {
40
+ path: string
41
+ exists: boolean
42
+ /** The workspace the source belongs to, or null for the deployment fallback. */
43
+ cwd: string | null
44
+ }
45
+
46
+ /** The complete settings-page snapshot served by `permissionRules/networkStatus`. */
47
+ export interface PermissionRulesSnapshot {
48
+ enabled: boolean
49
+ mode: NetworkModeWire
50
+ /** The configured mode knob (`auto` or an explicit mode). */
51
+ configuredMode: 'auto' | NetworkModeWire
52
+ /** The sandbox preset `auto` mapped from, or null. */
53
+ sandboxMode: string | null
54
+ proxyPort: number
55
+ proxyActive: boolean
56
+ denied: number
57
+ askBlocked: number
58
+ recent: readonly NetworkBlockView[]
59
+ sources: readonly RuleSourceView[]
60
+ }
61
+
62
+ /** Strict wire schema for {@link PermissionRulesSnapshot}. */
63
+ export const PERMISSION_RULES_SNAPSHOT_SCHEMA = z.object({
64
+ enabled: z.boolean(),
65
+ mode: z.union([z.literal('deny-all'), z.literal('whitelist'), z.literal('allow-all')]),
66
+ configuredMode: z.union([z.literal('auto'), z.literal('deny-all'), z.literal('whitelist'), z.literal('allow-all')]),
67
+ sandboxMode: z.string().nullable(),
68
+ proxyPort: z.number().int(),
69
+ proxyActive: z.boolean(),
70
+ denied: z.number().int(),
71
+ askBlocked: z.number().int(),
72
+ recent: z.array(z.object({
73
+ time: z.number().int(),
74
+ tool: z.string(),
75
+ attributed: z.boolean(),
76
+ domain: z.string(),
77
+ scheme: z.union([z.literal('http'), z.literal('https'), z.null()]),
78
+ port: z.number().int().nullable(),
79
+ action: z.union([z.literal('deny'), z.literal('ask')]),
80
+ mode: z.union([z.literal('deny-all'), z.literal('whitelist'), z.literal('allow-all')]),
81
+ matched: z.boolean(),
82
+ source: z.string(),
83
+ ruleIndex: z.number().int().nullable(),
84
+ reason: z.string().nullable(),
85
+ })),
86
+ sources: z.array(z.object({
87
+ path: z.string(),
88
+ exists: z.boolean(),
89
+ cwd: z.string().nullable(),
90
+ })),
91
+ })
92
+
93
+ /** Result of `permissionRules/rulesRead`. */
94
+ export interface RulesReadResult {
95
+ path: string
96
+ exists: boolean
97
+ text: string
98
+ error: string | null
99
+ }
100
+
101
+ /** Strict wire schema for {@link RulesReadResult}. */
102
+ export const RULES_READ_SCHEMA = z.object({
103
+ path: z.string(),
104
+ exists: z.boolean(),
105
+ text: z.string(),
106
+ error: z.string().nullable(),
107
+ })
108
+
109
+ /** Result of `permissionRules/rulesSave`. */
110
+ export interface RulesSaveResult {
111
+ ok: boolean
112
+ error: string | null
113
+ reloaded: number | null
114
+ }
115
+
116
+ /** Strict wire schema for {@link RulesSaveResult}. */
117
+ export const RULES_SAVE_SCHEMA = z.object({
118
+ ok: z.boolean(),
119
+ error: z.string().nullable(),
120
+ reloaded: z.number().int().nullable(),
121
+ })
122
+
123
+ /** Result of `permissionRules/reload`. */
124
+ export interface RulesReloadResult {
125
+ ok: boolean
126
+ error: string | null
127
+ }
128
+
129
+ /** Strict wire schema for {@link RulesReloadResult}. */
130
+ export const RULES_RELOAD_SCHEMA = z.object({
131
+ ok: z.boolean(),
132
+ error: z.string().nullable(),
133
+ })
134
+
135
+ /** The `permissionRules/networkStatus` invocation descriptor (no parameters). */
136
+ export const NETWORK_STATUS_DESCRIPTOR = Object.freeze({
137
+ id: 'dsh-permission-rules#permissionRules/networkStatus',
138
+ service: 'permissionRules',
139
+ namespace: 'permissionRules',
140
+ method: 'networkStatus',
141
+ invocation: Object.freeze({ kind: 'direct' }),
142
+ parameters: Object.freeze([]),
143
+ result: Object.freeze({
144
+ mode: 'strict',
145
+ typeSymbol: 'dsh-permission-rules/types#PermissionRulesSnapshot',
146
+ schema: PERMISSION_RULES_SNAPSHOT_SCHEMA,
147
+ }),
148
+ sourceLocation: Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 }),
149
+ } as const) satisfies InvocationDescriptor
150
+
151
+ /** The `permissionRules/rulesRead` invocation descriptor. */
152
+ export const RULES_READ_DESCRIPTOR = Object.freeze({
153
+ id: 'dsh-permission-rules#permissionRules/rulesRead',
154
+ service: 'permissionRules',
155
+ namespace: 'permissionRules',
156
+ method: 'rulesRead',
157
+ invocation: Object.freeze({ kind: 'direct' }),
158
+ parameters: Object.freeze([Object.freeze({
159
+ name: 'path',
160
+ wire: 'path',
161
+ source: 'json',
162
+ codec: Object.freeze({
163
+ mode: 'strict',
164
+ typeSymbol: 'dsh-permission-rules/types#RulesReadRequestPath',
165
+ schema: z.string(),
166
+ }),
167
+ } satisfies InvocationDescriptor['parameters'][number])]),
168
+ result: Object.freeze({
169
+ mode: 'strict',
170
+ typeSymbol: 'dsh-permission-rules/types#RulesReadResult',
171
+ schema: RULES_READ_SCHEMA,
172
+ }),
173
+ sourceLocation: Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 }),
174
+ } as const) satisfies InvocationDescriptor
175
+
176
+ /** The `permissionRules/rulesSave` invocation descriptor. */
177
+ export const RULES_SAVE_DESCRIPTOR = Object.freeze({
178
+ id: 'dsh-permission-rules#permissionRules/rulesSave',
179
+ service: 'permissionRules',
180
+ namespace: 'permissionRules',
181
+ method: 'rulesSave',
182
+ invocation: Object.freeze({ kind: 'direct' }),
183
+ parameters: Object.freeze([
184
+ Object.freeze({
185
+ name: 'path',
186
+ wire: 'path',
187
+ source: 'json',
188
+ codec: Object.freeze({
189
+ mode: 'strict',
190
+ typeSymbol: 'dsh-permission-rules/types#RulesSaveRequestPath',
191
+ schema: z.string(),
192
+ }),
193
+ } satisfies InvocationDescriptor['parameters'][number]),
194
+ Object.freeze({
195
+ name: 'text',
196
+ wire: 'text',
197
+ source: 'json',
198
+ codec: Object.freeze({
199
+ mode: 'strict',
200
+ typeSymbol: 'dsh-permission-rules/types#RulesSaveRequestText',
201
+ schema: z.string(),
202
+ }),
203
+ } satisfies InvocationDescriptor['parameters'][number]),
204
+ ]),
205
+ result: Object.freeze({
206
+ mode: 'strict',
207
+ typeSymbol: 'dsh-permission-rules/types#RulesSaveResult',
208
+ schema: RULES_SAVE_SCHEMA,
209
+ }),
210
+ sourceLocation: Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 }),
211
+ } as const) satisfies InvocationDescriptor
212
+
213
+ /** The `permissionRules/reload` invocation descriptor (no parameters). */
214
+ export const RULES_RELOAD_DESCRIPTOR = Object.freeze({
215
+ id: 'dsh-permission-rules#permissionRules/reload',
216
+ service: 'permissionRules',
217
+ namespace: 'permissionRules',
218
+ method: 'reload',
219
+ invocation: Object.freeze({ kind: 'direct' }),
220
+ parameters: Object.freeze([]),
221
+ result: Object.freeze({
222
+ mode: 'strict',
223
+ typeSymbol: 'dsh-permission-rules/types#RulesReloadResult',
224
+ schema: RULES_RELOAD_SCHEMA,
225
+ }),
226
+ sourceLocation: Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 }),
227
+ } as const) satisfies InvocationDescriptor
228
+
229
+ /**
230
+ * The canonical invocation list both Typert faces register — the host
231
+ * manifest and the client contribution share these exact descriptor
232
+ * objects, so the two wire codecs can never drift apart.
233
+ */
234
+ export const PERMISSION_RULES_INVOCATIONS = Object.freeze([
235
+ NETWORK_STATUS_DESCRIPTOR,
236
+ RULES_READ_DESCRIPTOR,
237
+ RULES_SAVE_DESCRIPTOR,
238
+ RULES_RELOAD_DESCRIPTOR,
239
+ ])
@@ -1,99 +0,0 @@
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
- enforce: z.boolean().default(true),
26
- allowUnmarkedAudit: z.boolean().default(false),
27
- });
28
- /**
29
- * Validate raw values and fill explicit defaults. A `maxRules`,
30
- * `maxCachedWorkspaces`, or `maxGlobStars` that is not a positive safe
31
- * integer, a non-positive stability window, `searchUp` combined with an
32
- * absolute `rulesFile`, a value outside a closed enum, or a non-boolean
33
- * flag throws here — misconfiguration fails loud at mount even when the
34
- * plugin is mounted without the Schemastery loader.
35
- * @param config - raw (possibly partial) plugin config.
36
- * @returns the fully resolved config.
37
- */
38
- export function resolveConfig(config = {}) {
39
- const rulesFile = config.rulesFile ?? '.dsh/rules.yaml';
40
- const searchUp = config.searchUp ?? false;
41
- if (searchUp && isAbsolute(rulesFile)) {
42
- throw new TypeError(`searchUp cannot be combined with an absolute rulesFile (${JSON.stringify(rulesFile)}): parent-directory walking needs a relative file name`);
43
- }
44
- const maxRules = config.maxRules ?? 256;
45
- if (!Number.isSafeInteger(maxRules) || maxRules <= 0) {
46
- throw new TypeError(`maxRules must be a positive safe integer, got ${String(config.maxRules)}`);
47
- }
48
- const watchStabilityThresholdMs = config.watchStabilityThresholdMs ?? 200;
49
- if (!Number.isSafeInteger(watchStabilityThresholdMs) || watchStabilityThresholdMs < 0) {
50
- throw new TypeError(`watchStabilityThresholdMs must be a non-negative safe integer, got ${String(config.watchStabilityThresholdMs)}`);
51
- }
52
- const maxCachedWorkspaces = config.maxCachedWorkspaces ?? 512;
53
- if (!Number.isSafeInteger(maxCachedWorkspaces) || maxCachedWorkspaces <= 0) {
54
- throw new TypeError(`maxCachedWorkspaces must be a positive safe integer, got ${String(config.maxCachedWorkspaces)}`);
55
- }
56
- const maxGlobStars = config.maxGlobStars ?? 2;
57
- if (!Number.isSafeInteger(maxGlobStars) || maxGlobStars <= 0) {
58
- throw new TypeError(`maxGlobStars must be a positive safe integer, got ${String(config.maxGlobStars)}`);
59
- }
60
- assertEnum('badFilePolicy', config.badFilePolicy ?? 'fail', ['fail', 'ignore-with-warning']);
61
- assertEnum('patternMode', config.patternMode ?? 'glob', ['glob', 'regex']);
62
- assertEnum('language', config.language ?? 'en', ['en', 'zh', 'es', 'pt', 'hi']);
63
- assertEnum('audit', config.audit ?? 'all', ['all', 'hits']);
64
- assertBoolean('watch', config.watch ?? true);
65
- assertBoolean('searchUp', searchUp);
66
- assertBoolean('caseInsensitivePaths', config.caseInsensitivePaths ?? process.platform === 'win32');
67
- assertBoolean('enforce', config.enforce ?? true);
68
- assertBoolean('allowUnmarkedAudit', config.allowUnmarkedAudit ?? false);
69
- return {
70
- rulesFile,
71
- fallbackPath: config.fallbackPath,
72
- badFilePolicy: config.badFilePolicy ?? 'fail',
73
- maxRules,
74
- maxCachedWorkspaces,
75
- patternMode: config.patternMode ?? 'glob',
76
- watch: config.watch ?? true,
77
- watchStabilityThresholdMs,
78
- language: config.language ?? 'en',
79
- caseInsensitivePaths: config.caseInsensitivePaths ?? process.platform === 'win32',
80
- audit: config.audit ?? 'all',
81
- searchUp,
82
- maxGlobStars,
83
- enforce: config.enforce ?? true,
84
- allowUnmarkedAudit: config.allowUnmarkedAudit ?? false,
85
- };
86
- }
87
- /** Throw unless `key` is one of `allowed` (TypeScript's closed enums are not runtime checks). */
88
- function assertEnum(key, value, allowed) {
89
- if (!allowed.includes(value)) {
90
- throw new TypeError(`${key} must be one of ${allowed.map(item => JSON.stringify(item)).join(' | ')}, got ${JSON.stringify(value)}`);
91
- }
92
- }
93
- /** Throw unless `key` is a boolean (plain-JS mounts bypass the Schemastery coercion). */
94
- function assertBoolean(key, value) {
95
- if (typeof value !== 'boolean') {
96
- throw new TypeError(`${key} must be a boolean, got ${typeof value}`);
97
- }
98
- }
99
- //# sourceMappingURL=config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
@@ -1,44 +0,0 @@
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
- * Under `enforce: false` (dry-run mode) the plugin matches but NEVER
15
- * short-circuits: the record keeps the WOULD-BE `action` and marks
16
- * `dryRun: true`, while `outcome` carries what actually happened
17
- * downstream — an auditable "what would the policy have done" trail.
18
- *
19
- * The event is appended with the envelope's `ignorable: true` marker (see
20
- * {@link AuditAppend}). Harness builds that honor the marker (post-rc.6)
21
- * stamp it on the envelope and skip unknown ignorable records when loading,
22
- * so the audit can never refuse a session. Builds whose `Session.append`
23
- * predates the marker — the `0.1.0-rc.6` line — silently DROP the options
24
- * bag: the event then lands UNMARKED and makes the session unresumable on
25
- * hosts with required-on-read semantics (`SessionFormatUnsupportedError`).
26
- * The runtime detects this at first use (peer version pre-check plus a
27
- * probe of the appended envelope) and disables session-log audit on such
28
- * hosts with a one-time warning; `allowUnmarkedAudit: true` opts back in,
29
- * and `scripts/repair-session-logs.mjs` repairs already-polluted logs.
30
- * @module dsh-permission-rules/events
31
- */
32
- /**
33
- * Whether an `append` call actually honored the `ignorable` marker: the
34
- * logged event returned by the host carries `ignorable === true` on
35
- * marker-aware builds and nothing on pre-marker builds. `false` (or any
36
- * non-event return) means the host dropped the marker and the event landed
37
- * unmarked — the runtime then degrades instead of polluting further logs.
38
- * @param result - the return value of the audit append.
39
- * @returns true only when the marker is present on the returned envelope.
40
- */
41
- export function isMarkedAuditEvent(result) {
42
- return typeof result === 'object' && result !== null && result.ignorable === true;
43
- }
44
- //# sourceMappingURL=events.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAoEH;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAe;IAChD,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAK,MAAkC,CAAC,SAAS,KAAK,IAAI,CAAA;AAChH,CAAC"}