dsh-perm-gate 4.1.0-beta.1 → 4.1.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/lib/client.js +14 -14
- package/lib/client.js.map +1 -1
- package/lib/index.js +34 -7
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { Config, resolveDshHome, resolveDataDir, ensureDataDir, resolveGatePresets, resolvePermissiveStrategies, resolveRulesFile } from './config.js';
|
|
3
|
+
import { Config, RULES_NAMESPACE, RulesSchema, readRulesFromSettings, resolveDshHome, resolveDataDir, ensureDataDir, resolveGatePresets, resolvePermissiveStrategies, resolveRulesFile } from './config.js';
|
|
4
4
|
import { runDryRun } from './dry-run.js';
|
|
5
5
|
import { registerDryRunRoute, registerEventsRoute, registerHealthRoute, registerLearningRoute, registerNetworkRoute, registerReceiverRoute, registerReviewRoutes, registerRulesRoute } from './events.js';
|
|
6
6
|
import { buildReceiverInfo } from './receiver-info.js';
|
|
7
|
-
import { readRulesView } from './rules-view.js';
|
|
7
|
+
import { readRulesView, readRulesViewFromSettings } from './rules-view.js';
|
|
8
8
|
import { PermGateRuntime } from './runtime.js';
|
|
9
9
|
import { classifySessions, sweepSessionData } from './session-sweep.js';
|
|
10
10
|
import { decideNetworkTarget } from './network.js';
|
|
@@ -192,6 +192,11 @@ export function apply(ctx, config = {}) {
|
|
|
192
192
|
// Runtime-adjustable config: the composition entry is the base; the settings
|
|
193
193
|
// namespace layers on top and `current()` always reads the active section.
|
|
194
194
|
let current = () => config;
|
|
195
|
+
// ─── Rules settings scope (dsh-perm-gate-rules namespace) ────────────────
|
|
196
|
+
// Holds the live settings-sourced rules document. When non-undefined, the
|
|
197
|
+
// runtime prefers it over the rules file on disk.
|
|
198
|
+
let rulesScope;
|
|
199
|
+
const readRulesDocument = () => readRulesFromSettings(rulesScope);
|
|
195
200
|
// Plugin-owned data files live under $DSH_HOME (node_modules may be
|
|
196
201
|
// read-only). The default resolves to `$DSH_HOME` / `~/.dsh`, so a profile
|
|
197
202
|
// entry that omits `config` still records events, snapshots and learning.
|
|
@@ -338,6 +343,8 @@ export function apply(ctx, config = {}) {
|
|
|
338
343
|
// `$DSH_HOME/perm-gate/rules.yml` the user writes is actually loaded without
|
|
339
344
|
// also having to declare `rulesFile` in the composition entry.
|
|
340
345
|
rulesFile: resolveRulesFile(typeof config.rulesFile === 'string' ? config.rulesFile : undefined, dataDir),
|
|
346
|
+
// Settings-sourced rules take precedence over the file when present.
|
|
347
|
+
readRulesDocument,
|
|
341
348
|
// The whole gate is scoped to the presets that opt into it (default: the
|
|
342
349
|
// `permissive` tier this plugin adds); elsewhere it stands down entirely.
|
|
343
350
|
gatePresets: resolveGatePresets(Array.isArray(config.gatePresets) ? config.gatePresets : undefined),
|
|
@@ -456,6 +463,21 @@ export function apply(ctx, config = {}) {
|
|
|
456
463
|
});
|
|
457
464
|
},
|
|
458
465
|
});
|
|
466
|
+
// ─── Rules settings namespace (dsh-perm-gate-rules) ─────────────────────
|
|
467
|
+
// Registers the rules document in its own DSH settings namespace so the gate
|
|
468
|
+
// loads rules from settings (when configured) instead of the rules file.
|
|
469
|
+
installSettingsSection(ctx, RULES_NAMESPACE, RulesSchema, {}, {
|
|
470
|
+
setSource: (source) => {
|
|
471
|
+
rulesScope = { get: source };
|
|
472
|
+
},
|
|
473
|
+
onChange: () => { },
|
|
474
|
+
onScope: (scope) => {
|
|
475
|
+
rulesScope = scope;
|
|
476
|
+
// When rules change in settings, reload the runtime so the new ruleset
|
|
477
|
+
// takes effect on the next tool call.
|
|
478
|
+
scope.watch(() => { runtime.reload(); });
|
|
479
|
+
},
|
|
480
|
+
});
|
|
459
481
|
// Event feed HTTP API (best effort): the dsh webServer service exposes the
|
|
460
482
|
// JSONL decision events to the browser half; without it events stay on disk.
|
|
461
483
|
try {
|
|
@@ -518,12 +540,17 @@ export function apply(ctx, config = {}) {
|
|
|
518
540
|
});
|
|
519
541
|
if (offDryRun !== undefined)
|
|
520
542
|
ctx.effect(() => () => { offDryRun(); }, 'dsh-perm-gate: dry-run route');
|
|
521
|
-
// Permissions
|
|
522
|
-
//
|
|
523
|
-
// resolved exactly as the gate resolves it — a view that resolved its own
|
|
524
|
-
// path could describe a different file than the one in force.
|
|
543
|
+
// Permissions view: prefer the settings namespace (dsh-perm-gate-rules)
|
|
544
|
+
// when it carries a real configuration; fall back to the rules file.
|
|
525
545
|
const rulesFilePath = resolveRulesFile(typeof config.rulesFile === 'string' ? config.rulesFile : undefined, dataDir);
|
|
526
|
-
const offRules = registerRulesRoute(webServer, {
|
|
546
|
+
const offRules = registerRulesRoute(webServer, {
|
|
547
|
+
view: () => {
|
|
548
|
+
const settingsDoc = readRulesDocument();
|
|
549
|
+
return settingsDoc !== undefined
|
|
550
|
+
? readRulesViewFromSettings(settingsDoc)
|
|
551
|
+
: readRulesView(rulesFilePath);
|
|
552
|
+
},
|
|
553
|
+
});
|
|
527
554
|
if (offRules !== undefined)
|
|
528
555
|
ctx.effect(() => () => { offRules(); }, 'dsh-perm-gate: rules route');
|
|
529
556
|
// Receiver projection for the settings card (provider/model catalog is
|