@yadsh/dsh-prompt-firewall 0.1.1 → 0.1.3
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/README.md +1 -1
- package/compatibility.json +16 -0
- package/lib/client/index.js +32 -78
- package/lib/client/index.js.map +1 -1
- package/lib/client/sections.js +75 -0
- package/lib/client/sections.js.map +1 -0
- package/lib/client/styles.js +16 -5
- package/lib/client/styles.js.map +1 -1
- package/lib/client.js +757 -557
- package/lib/client.js.map +1 -1
- package/lib/index.js +17 -1
- package/lib/index.js.map +1 -1
- package/lib/typert.host.js +2 -2
- package/lib/typert.remote-client.js +2 -2
- package/lib/types/audit.d.ts +1 -0
- package/lib/types/client/index.d.ts +1 -0
- package/lib/types/client/sections.d.ts +39 -0
- package/lib/types/client/styles.d.ts +1 -0
- package/lib/types/config.d.ts +1 -0
- package/lib/types/firewall.d.ts +1 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/metrics.d.ts +1 -0
- package/lib/types/presets.d.ts +1 -0
- package/lib/types/rules.d.ts +1 -0
- package/lib/types/types.d.ts +1 -0
- package/package.json +13 -7
package/lib/client.js
CHANGED
|
@@ -4,8 +4,8 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
-
let react = require("react");
|
|
8
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
9
|
//#region ../../node_modules/.pnpm/zod@4.5.2/node_modules/zod/v4/core/util.js
|
|
10
10
|
function getEnumValues(entries) {
|
|
11
11
|
const numericValues = Object.values(entries).filter((v) => typeof v === "number");
|
|
@@ -5124,7 +5124,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5124
5124
|
},
|
|
5125
5125
|
sourceLocation: {
|
|
5126
5126
|
"file": "packages/dsh-prompt-firewall/src/index.ts",
|
|
5127
|
-
"line":
|
|
5127
|
+
"line": 140,
|
|
5128
5128
|
"column": 3
|
|
5129
5129
|
}
|
|
5130
5130
|
}, {
|
|
@@ -5173,45 +5173,200 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5173
5173
|
},
|
|
5174
5174
|
sourceLocation: {
|
|
5175
5175
|
"file": "packages/dsh-prompt-firewall/src/index.ts",
|
|
5176
|
-
"line":
|
|
5176
|
+
"line": 154,
|
|
5177
5177
|
"column": 9
|
|
5178
5178
|
}
|
|
5179
5179
|
}]
|
|
5180
5180
|
};
|
|
5181
5181
|
//#endregion
|
|
5182
|
-
//#region
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5182
|
+
//#region ../../packages/plugin-kit/lib/client/plugin-card-css.js
|
|
5183
|
+
/**
|
|
5184
|
+
* Canonical DSH settings-plugin card shell CSS — the single source of truth
|
|
5185
|
+
* for the shared `dsh-plugin-card` outer shell (see AGENTS.md). Plugins must
|
|
5186
|
+
* inject this CSS unchanged and may only append rules for their own controls
|
|
5187
|
+
* inside the card body; plugin-specific shell styling is forbidden.
|
|
5188
|
+
*/
|
|
5189
|
+
const PLUGIN_CARD_SHELL_CSS = `
|
|
5190
|
+
.dsh-plugin-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}
|
|
5191
|
+
.dsh-plugin-card:hover{border-color:var(--dsw-alias-label-dimmed)}
|
|
5192
|
+
.dsh-plugin-card--open{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}
|
|
5193
|
+
.dsh-plugin-card__header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}
|
|
5194
|
+
.dsh-plugin-card__header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}
|
|
5195
|
+
.dsh-plugin-card__head-text{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}
|
|
5196
|
+
.dsh-plugin-card__name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}
|
|
5197
|
+
.dsh-plugin-card__description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}
|
|
5198
|
+
.dsh-plugin-card__badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
5199
|
+
.dsh-plugin-card__chevron{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}
|
|
5200
|
+
.dsh-plugin-card--open .dsh-plugin-card__chevron{transform:rotate(180deg)}
|
|
5201
|
+
.dsh-plugin-card__body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}
|
|
5188
5202
|
`;
|
|
5189
5203
|
//#endregion
|
|
5190
|
-
//#region
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
function
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
function Shield() {
|
|
5203
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5204
|
-
className: "pf-shield",
|
|
5204
|
+
//#region ../../packages/plugin-kit/lib/client/chevron.js
|
|
5205
|
+
/**
|
|
5206
|
+
* The standard disclosure chevron of the shared settings-card shell: a
|
|
5207
|
+
* 14x14 inline SVG stroked with `currentColor` (round caps and joins).
|
|
5208
|
+
* Font glyphs must not be used for this shape — their appearance and
|
|
5209
|
+
* baseline vary by font and encoding.
|
|
5210
|
+
*/
|
|
5211
|
+
function ChevronDown() {
|
|
5212
|
+
return (0, react_jsx_runtime.jsx)("svg", {
|
|
5213
|
+
className: "dsh-plugin-card__chevron",
|
|
5214
|
+
viewBox: "0 0 14 14",
|
|
5215
|
+
fill: "none",
|
|
5205
5216
|
"aria-hidden": "true",
|
|
5206
|
-
children:
|
|
5207
|
-
|
|
5208
|
-
fill: "none",
|
|
5217
|
+
children: (0, react_jsx_runtime.jsx)("path", {
|
|
5218
|
+
d: "m3.5 5.25 3.5 3.5 3.5-3.5",
|
|
5209
5219
|
stroke: "currentColor",
|
|
5210
|
-
|
|
5211
|
-
|
|
5220
|
+
strokeLinecap: "round",
|
|
5221
|
+
strokeLinejoin: "round"
|
|
5212
5222
|
})
|
|
5213
5223
|
});
|
|
5214
5224
|
}
|
|
5225
|
+
//#endregion
|
|
5226
|
+
//#region ../../packages/plugin-kit/lib/client/card-shell.js
|
|
5227
|
+
/**
|
|
5228
|
+
* Shared outer shell of a plugin configuration card (AGENTS.md contract): a
|
|
5229
|
+
* direct `<li>` child of the host list with a full-width header button
|
|
5230
|
+
* (`type="button"`, `aria-expanded`, accessible show/hide label, the
|
|
5231
|
+
* title/description stack, an optional status badge, then the chevron) and a
|
|
5232
|
+
* body rendered only while open. Plugin-specific controls belong inside the
|
|
5233
|
+
* body and must not restyle the shell.
|
|
5234
|
+
*/
|
|
5235
|
+
function CardShell(props) {
|
|
5236
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
5237
|
+
const body = props.bodyClassName === void 0 ? "dsh-plugin-card__body" : `dsh-plugin-card__body ${props.bodyClassName}`;
|
|
5238
|
+
return (0, react_jsx_runtime.jsxs)("li", {
|
|
5239
|
+
className: open ? "dsh-plugin-card dsh-plugin-card--open" : "dsh-plugin-card",
|
|
5240
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
5241
|
+
type: "button",
|
|
5242
|
+
className: "dsh-plugin-card__header",
|
|
5243
|
+
"aria-expanded": open,
|
|
5244
|
+
"aria-label": props.label(open),
|
|
5245
|
+
onClick: () => {
|
|
5246
|
+
setOpen(!open);
|
|
5247
|
+
},
|
|
5248
|
+
children: [
|
|
5249
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
5250
|
+
className: "dsh-plugin-card__head-text",
|
|
5251
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
5252
|
+
className: "dsh-plugin-card__name",
|
|
5253
|
+
children: props.title
|
|
5254
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
5255
|
+
className: "dsh-plugin-card__description",
|
|
5256
|
+
children: props.description
|
|
5257
|
+
})]
|
|
5258
|
+
}),
|
|
5259
|
+
props.badge ?? null,
|
|
5260
|
+
(0, react_jsx_runtime.jsx)(ChevronDown, {})
|
|
5261
|
+
]
|
|
5262
|
+
}), open ? (0, react_jsx_runtime.jsx)("div", {
|
|
5263
|
+
className: body,
|
|
5264
|
+
children: props.children
|
|
5265
|
+
}) : null]
|
|
5266
|
+
});
|
|
5267
|
+
}
|
|
5268
|
+
function noop() {}
|
|
5269
|
+
/**
|
|
5270
|
+
* Inject one stylesheet tag for the plugin's card CSS. The tag carries
|
|
5271
|
+
* `data-plugin="<pluginName>"` and is guarded against double injection; the
|
|
5272
|
+
* returned disposer removes the tag when this call created it. No-op in
|
|
5273
|
+
* non-DOM environments (headless bundles, module probes).
|
|
5274
|
+
*/
|
|
5275
|
+
function injectCardStyles(pluginName, css) {
|
|
5276
|
+
if (typeof document === "undefined") return noop;
|
|
5277
|
+
const selector = `style[data-plugin="${pluginName}"]`;
|
|
5278
|
+
if (typeof document.querySelector === "function" && document.querySelector(selector) !== null) return noop;
|
|
5279
|
+
const tag = document.createElement("style");
|
|
5280
|
+
tag.dataset.plugin = pluginName;
|
|
5281
|
+
tag.textContent = css;
|
|
5282
|
+
document.head.appendChild(tag);
|
|
5283
|
+
return () => {
|
|
5284
|
+
tag.remove();
|
|
5285
|
+
};
|
|
5286
|
+
}
|
|
5287
|
+
/**
|
|
5288
|
+
* Register the card component into the shared settings-plugins slot. Returns
|
|
5289
|
+
* the registration disposer. Use this variant when the plugin drives the
|
|
5290
|
+
* slot's inject-factory itself (e.g. to dispose a form controller alongside).
|
|
5291
|
+
*/
|
|
5292
|
+
function registerSettingsSlot(host, options) {
|
|
5293
|
+
const slotOptions = {
|
|
5294
|
+
name: options.slotName ?? "settings.plugin.item",
|
|
5295
|
+
key: options.key,
|
|
5296
|
+
...options.locale === void 0 ? {} : { locale: options.locale },
|
|
5297
|
+
...options.inject === void 0 ? {} : { inject: options.inject }
|
|
5298
|
+
};
|
|
5299
|
+
return host.slots.register(slotOptions, options.component);
|
|
5300
|
+
}
|
|
5301
|
+
/**
|
|
5302
|
+
* Full bootstrap: inject {@link options.styles} once (when provided), then
|
|
5303
|
+
* mount the card into the settings-plugins slot. Returns a disposer removing
|
|
5304
|
+
* the slot effect and the injected stylesheet.
|
|
5305
|
+
*/
|
|
5306
|
+
function registerSettingsCard(host, options) {
|
|
5307
|
+
const removeStyles = options.styles === void 0 || options.pluginName === void 0 ? void 0 : injectCardStyles(options.pluginName, options.styles);
|
|
5308
|
+
const slotName = options.slotName ?? "settings.plugin.item";
|
|
5309
|
+
const disposeEffect = host.slots.inject(slotName, () => registerSettingsSlot(host, options));
|
|
5310
|
+
return () => {
|
|
5311
|
+
disposeEffect();
|
|
5312
|
+
removeStyles?.();
|
|
5313
|
+
};
|
|
5314
|
+
}
|
|
5315
|
+
//#endregion
|
|
5316
|
+
//#region ../../packages/plugin-kit/lib/client/settings-store.js
|
|
5317
|
+
/**
|
|
5318
|
+
* React calls external-store callbacks as plain functions, while
|
|
5319
|
+
* SettingsScope's methods depend on their receiver. Forwarding the methods
|
|
5320
|
+
* directly loses `this` and crashes while reading the internal store, so
|
|
5321
|
+
* bind them through stable wrappers.
|
|
5322
|
+
*/
|
|
5323
|
+
function bindSettingsExternalStore(scope) {
|
|
5324
|
+
return {
|
|
5325
|
+
subscribe: (listener) => scope.subscribe(listener),
|
|
5326
|
+
getSnapshot: () => scope.getSnapshot()
|
|
5327
|
+
};
|
|
5328
|
+
}
|
|
5329
|
+
//#endregion
|
|
5330
|
+
//#region ../../packages/plugin-kit/lib/client/polling.js
|
|
5331
|
+
function startVisibilityAwarePolling(refresh, intervalMs, visibilityDocument = document, pollingWindow = window) {
|
|
5332
|
+
const refreshWhenVisible = () => {
|
|
5333
|
+
if (!visibilityDocument.hidden) refresh();
|
|
5334
|
+
};
|
|
5335
|
+
const handleVisibilityChange = () => {
|
|
5336
|
+
refreshWhenVisible();
|
|
5337
|
+
};
|
|
5338
|
+
refreshWhenVisible();
|
|
5339
|
+
const timer = pollingWindow.setInterval(refreshWhenVisible, intervalMs);
|
|
5340
|
+
visibilityDocument.addEventListener("visibilitychange", handleVisibilityChange);
|
|
5341
|
+
return () => {
|
|
5342
|
+
pollingWindow.clearInterval(timer);
|
|
5343
|
+
visibilityDocument.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
5344
|
+
};
|
|
5345
|
+
}
|
|
5346
|
+
//#endregion
|
|
5347
|
+
//#region src/client/styles.ts
|
|
5348
|
+
const styles = `${PLUGIN_CARD_SHELL_CSS}
|
|
5349
|
+
.pf-body,.pf-body *{box-sizing:border-box}
|
|
5350
|
+
.pf-body{padding-top:16px;display:grid;gap:18px;color:var(--dsw-alias-label-primary)}
|
|
5351
|
+
.pf-section{display:grid;gap:12px}.pf-section-title{display:flex;justify-content:space-between;align-items:center;gap:12px}.pf-section-title h3{font-size:13px;margin:0}.pf-muted{color:var(--dsw-alias-label-tertiary);font-size:12px;margin:0;line-height:1.5}
|
|
5352
|
+
.pf-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:11px}.pf-field{display:grid;gap:6px}.pf-field>span{font-size:11px;color:var(--dsw-alias-label-secondary);font-weight:600}
|
|
5353
|
+
.pf-control{width:100%;height:36px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);padding:0 10px;font:inherit;font-size:12px;outline:none}.pf-control:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-1px}
|
|
5354
|
+
.pf-toggle-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px}.pf-toggle-copy{display:grid;gap:2px}.pf-toggle-copy strong{font-size:12px;font-weight:500}.pf-toggle-copy span{font-size:10px;color:var(--dsw-alias-label-tertiary)}
|
|
5355
|
+
.pf-toggle{appearance:none;width:34px;height:19px;border-radius:999px;background:var(--dsw-alias-label-dimmed);position:relative;cursor:pointer;transition:.18s;flex:none}.pf-toggle:after{content:'';position:absolute;top:3px;left:3px;width:13px;height:13px;border-radius:50%;background:var(--dsw-alias-bg-layer-3);transition:.18s}.pf-toggle:checked{background:var(--dsw-alias-brand-primary)}.pf-toggle:checked:after{transform:translateX(15px)}
|
|
5356
|
+
.pf-toggle:disabled,.pf-control:disabled,.pf-btn:disabled{cursor:default;opacity:.45}
|
|
5357
|
+
.pf-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}.pf-stat{padding:12px;border-radius:9px;background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l2)}.pf-stat b{display:block;font-size:17px;margin-bottom:3px}.pf-stat span{font-size:10px;color:var(--dsw-alias-label-tertiary)}
|
|
5358
|
+
.pf-editor{display:grid;grid-template-columns:1.2fr .8fr .8fr auto;gap:8px}.pf-btn{height:34px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);padding:0 12px;font:inherit;font-size:11px;font-weight:600;cursor:pointer;white-space:nowrap}.pf-btn:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed);background:var(--dsw-alias-interactive-bg-hover)}.pf-btn.primary{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-bg-layer-3)}.pf-btn.danger{color:var(--dsw-alias-label-error)}.pf-btn.link{height:27px;padding:0 8px;background:transparent}
|
|
5359
|
+
.pf-rules{display:grid;gap:6px}.pf-rule{display:grid;grid-template-columns:minmax(0,1fr) 70px 70px auto;gap:9px;align-items:center;padding:7px 9px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;font-size:11px}.pf-rule code{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary)}.pf-pill{font-size:9px;text-transform:uppercase;letter-spacing:.04em;color:var(--dsw-alias-label-tertiary)}.pf-pill.block{color:var(--dsw-alias-label-error)}.pf-pill.allow{color:var(--dsw-alias-state-business-primary)}.pf-pill.protect{color:var(--dsw-alias-brand-primary)}
|
|
5360
|
+
.pf-advanced{border:1px solid var(--dsw-alias-border-l2);border-radius:10px;padding:0 12px}.pf-advanced summary{cursor:pointer;padding:11px 0;font-size:12px;font-weight:600}.pf-advanced-content{padding:2px 0 13px;display:grid;gap:10px}
|
|
5361
|
+
.pf-table-wrap{overflow:auto;border:1px solid var(--dsw-alias-border-l2);border-radius:10px}.pf-table{width:100%;border-collapse:collapse;font-size:11px;min-width:720px}.pf-table th{text-align:left;color:var(--dsw-alias-label-tertiary);font-weight:600;background:var(--dsw-alias-bg-module-platform);padding:8px 10px}.pf-table td{padding:9px 10px;border-top:1px solid var(--dsw-alias-border-l2);vertical-align:top}.pf-section-name{display:flex;align-items:center;gap:6px;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.pf-new,.pf-warn{font-family:inherit;font-size:8px;font-weight:800;border-radius:4px;padding:2px 4px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-brand-primary)}.pf-warn{color:var(--dsw-alias-label-secondary)}.pf-actions{display:flex;gap:4px}.pf-preview{margin-top:5px;max-width:360px;white-space:pre-wrap;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:1.4}.pf-empty{padding:22px;text-align:center;color:var(--dsw-alias-label-tertiary);font-size:12px}.pf-error{padding:9px 11px;border-radius:8px;background:var(--dsw-alias-bg-error);color:var(--dsw-alias-label-error);font-size:11px}.pf-footer-note{font-size:10px;color:var(--dsw-alias-label-tertiary)}
|
|
5362
|
+
@media(max-width:720px){.pf-grid{grid-template-columns:1fr}.pf-stats{grid-template-columns:repeat(2,minmax(0,1fr))}.pf-editor{grid-template-columns:1fr 1fr}.pf-editor input{grid-column:1/-1}.pf-rule{grid-template-columns:minmax(0,1fr) 58px auto}.pf-rule .pf-kind{display:none}}
|
|
5363
|
+
`;
|
|
5364
|
+
//#endregion
|
|
5365
|
+
//#region src/client/sections.tsx
|
|
5366
|
+
const EMPTY_LIST = Object.freeze([]);
|
|
5367
|
+
function list(config, field) {
|
|
5368
|
+
return config?.[field] ?? EMPTY_LIST;
|
|
5369
|
+
}
|
|
5215
5370
|
function Toggle(props) {
|
|
5216
5371
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5217
5372
|
className: "pf-toggle-row",
|
|
@@ -5229,66 +5384,163 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5229
5384
|
})]
|
|
5230
5385
|
});
|
|
5231
5386
|
}
|
|
5232
|
-
function
|
|
5233
|
-
const
|
|
5234
|
-
const
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5387
|
+
function PolicySection(props) {
|
|
5388
|
+
const { config, writable, setPath } = props;
|
|
5389
|
+
const configuredMode = config?.mode ?? (config?.preset === "strict" ? "allowlist" : config?.preset === "audit-only" ? "audit" : "blocklist");
|
|
5390
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5391
|
+
className: "pf-section",
|
|
5392
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5393
|
+
className: "pf-section-title",
|
|
5394
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Policy" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5395
|
+
className: "pf-muted",
|
|
5396
|
+
children: "Changes apply live"
|
|
5397
|
+
})]
|
|
5398
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5399
|
+
className: "pf-grid",
|
|
5400
|
+
children: [
|
|
5401
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5402
|
+
checked: config?.enabled ?? true,
|
|
5403
|
+
disabled: !writable,
|
|
5404
|
+
label: "Firewall enabled",
|
|
5405
|
+
hint: "Keep auditing available when policy is off.",
|
|
5406
|
+
onChange: (value) => {
|
|
5407
|
+
setPath(["enabled"], value);
|
|
5408
|
+
}
|
|
5409
|
+
}),
|
|
5410
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5411
|
+
checked: config?.protectCoreSections ?? true,
|
|
5412
|
+
disabled: !writable,
|
|
5413
|
+
label: "Protect core sections",
|
|
5414
|
+
hint: "Prevents ordinary rules from removing Harness internals.",
|
|
5415
|
+
onChange: (value) => {
|
|
5416
|
+
setPath(["protectCoreSections"], value);
|
|
5417
|
+
}
|
|
5418
|
+
}),
|
|
5419
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5420
|
+
className: "pf-field",
|
|
5421
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Mode" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5422
|
+
className: "pf-control",
|
|
5423
|
+
value: configuredMode,
|
|
5424
|
+
disabled: !writable,
|
|
5425
|
+
onChange: (event) => {
|
|
5426
|
+
setPath(["mode"], event.currentTarget.value);
|
|
5427
|
+
},
|
|
5428
|
+
children: [
|
|
5429
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5430
|
+
value: "off",
|
|
5431
|
+
children: "Off"
|
|
5432
|
+
}),
|
|
5433
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5434
|
+
value: "audit",
|
|
5435
|
+
children: "Audit only"
|
|
5436
|
+
}),
|
|
5437
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5438
|
+
value: "blocklist",
|
|
5439
|
+
children: "Blocklist"
|
|
5440
|
+
}),
|
|
5441
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5442
|
+
value: "allowlist",
|
|
5443
|
+
children: "Allowlist"
|
|
5444
|
+
})
|
|
5445
|
+
]
|
|
5446
|
+
})]
|
|
5447
|
+
}),
|
|
5448
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5449
|
+
className: "pf-field",
|
|
5450
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Preset" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5451
|
+
className: "pf-control",
|
|
5452
|
+
value: config?.preset ?? "",
|
|
5453
|
+
disabled: !writable,
|
|
5454
|
+
onChange: (event) => {
|
|
5455
|
+
const value = event.currentTarget.value;
|
|
5456
|
+
if (value === "") props.unsetPreset();
|
|
5457
|
+
else setPath(["preset"], value);
|
|
5458
|
+
},
|
|
5459
|
+
children: [
|
|
5460
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5461
|
+
value: "",
|
|
5462
|
+
children: "None"
|
|
5463
|
+
}),
|
|
5464
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5465
|
+
value: "clean",
|
|
5466
|
+
children: "Clean"
|
|
5467
|
+
}),
|
|
5468
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5469
|
+
value: "strict",
|
|
5470
|
+
children: "Strict"
|
|
5471
|
+
}),
|
|
5472
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5473
|
+
value: "audit-only",
|
|
5474
|
+
children: "Audit only"
|
|
5475
|
+
})
|
|
5476
|
+
]
|
|
5477
|
+
})]
|
|
5478
|
+
}),
|
|
5479
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5480
|
+
className: "pf-field",
|
|
5481
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Unknown plugin sections" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5482
|
+
className: "pf-control",
|
|
5483
|
+
value: config?.unknownPluginPolicy ?? "allow",
|
|
5484
|
+
disabled: !writable,
|
|
5485
|
+
onChange: (event) => {
|
|
5486
|
+
setPath(["unknownPluginPolicy"], event.currentTarget.value);
|
|
5487
|
+
},
|
|
5488
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5489
|
+
value: "allow",
|
|
5490
|
+
children: "Allow"
|
|
5491
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5492
|
+
value: "block",
|
|
5493
|
+
children: "Block"
|
|
5494
|
+
})]
|
|
5495
|
+
})]
|
|
5496
|
+
})
|
|
5497
|
+
]
|
|
5498
|
+
})]
|
|
5499
|
+
});
|
|
5500
|
+
}
|
|
5501
|
+
function LastRequestSection(props) {
|
|
5502
|
+
const last = props.inspector?.last ?? null;
|
|
5503
|
+
const effectiveMode = props.inspector?.config.mode ?? props.config?.mode ?? "blocklist";
|
|
5504
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5505
|
+
className: "pf-section",
|
|
5506
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5507
|
+
className: "pf-section-title",
|
|
5508
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Last request" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5509
|
+
className: "pf-btn",
|
|
5510
|
+
disabled: props.refreshing,
|
|
5511
|
+
onClick: () => {
|
|
5512
|
+
props.onRefresh();
|
|
5513
|
+
},
|
|
5514
|
+
children: props.refreshing ? "Refreshing…" : "Refresh"
|
|
5515
|
+
})]
|
|
5516
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5517
|
+
className: "pf-stats",
|
|
5518
|
+
children: [
|
|
5519
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5520
|
+
className: "pf-stat",
|
|
5521
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: last?.totalSections ?? "—" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "sections" })]
|
|
5522
|
+
}),
|
|
5523
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5524
|
+
className: "pf-stat",
|
|
5525
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: last?.blockedSections ?? "—" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "blocked" })]
|
|
5526
|
+
}),
|
|
5527
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5528
|
+
className: "pf-stat",
|
|
5529
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: last === null ? "—" : "~" + String(last.estimatedTokensRemoved) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "tokens removed (estimate)" })]
|
|
5530
|
+
}),
|
|
5531
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5532
|
+
className: "pf-stat",
|
|
5533
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: effectiveMode }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "effective mode" })]
|
|
5534
|
+
})
|
|
5535
|
+
]
|
|
5536
|
+
})]
|
|
5537
|
+
});
|
|
5538
|
+
}
|
|
5539
|
+
function RulesSection(props) {
|
|
5540
|
+
const { config, writable, setPath } = props;
|
|
5239
5541
|
const [rule, setRule] = (0, react.useState)("");
|
|
5240
5542
|
const [ruleKind, setRuleKind] = (0, react.useState)("exact");
|
|
5241
5543
|
const [ruleAction, setRuleAction] = (0, react.useState)("block");
|
|
5242
|
-
const activeRequest = (0, react.useRef)(0);
|
|
5243
|
-
const refresh = (0, react.useCallback)(async () => {
|
|
5244
|
-
const request = ++activeRequest.current;
|
|
5245
|
-
setRefreshing(true);
|
|
5246
|
-
try {
|
|
5247
|
-
const result = await inspect();
|
|
5248
|
-
if (request !== activeRequest.current) return;
|
|
5249
|
-
if (result.ok) {
|
|
5250
|
-
setInspector(result.value);
|
|
5251
|
-
setError(null);
|
|
5252
|
-
} else setError(displayError(result.error));
|
|
5253
|
-
} catch (cause) {
|
|
5254
|
-
if (request === activeRequest.current) setError(displayError(cause));
|
|
5255
|
-
} finally {
|
|
5256
|
-
if (request === activeRequest.current) setRefreshing(false);
|
|
5257
|
-
}
|
|
5258
|
-
}, [inspect]);
|
|
5259
|
-
(0, react.useEffect)(() => {
|
|
5260
|
-
refresh();
|
|
5261
|
-
const interval = window.setInterval(() => {
|
|
5262
|
-
refresh();
|
|
5263
|
-
}, REFRESH_INTERVAL_MS);
|
|
5264
|
-
return () => {
|
|
5265
|
-
window.clearInterval(interval);
|
|
5266
|
-
activeRequest.current += 1;
|
|
5267
|
-
};
|
|
5268
|
-
}, [refresh]);
|
|
5269
|
-
const setPath = (0, react.useCallback)((path, value) => {
|
|
5270
|
-
const [field, nested] = path;
|
|
5271
|
-
if (field === void 0) return;
|
|
5272
|
-
if (nested === void 0) {
|
|
5273
|
-
scope.set(field, value);
|
|
5274
|
-
return;
|
|
5275
|
-
}
|
|
5276
|
-
const current = scope.getSnapshot().value;
|
|
5277
|
-
const parent = field === "audit" ? current?.audit : current?.metrics;
|
|
5278
|
-
scope.set(field, {
|
|
5279
|
-
...parent,
|
|
5280
|
-
[nested]: value
|
|
5281
|
-
});
|
|
5282
|
-
}, [scope]);
|
|
5283
|
-
const setPolicy = (0, react.useCallback)(async (name, policy) => {
|
|
5284
|
-
const result = await setSectionPolicy(name, policy, scope.getSnapshot().revision);
|
|
5285
|
-
if (!result.ok) setError(displayError(result.error));
|
|
5286
|
-
await refresh();
|
|
5287
|
-
}, [
|
|
5288
|
-
refresh,
|
|
5289
|
-
scope,
|
|
5290
|
-
setSectionPolicy
|
|
5291
|
-
]);
|
|
5292
5544
|
const addRule = (event) => {
|
|
5293
5545
|
event.preventDefault();
|
|
5294
5546
|
const value = rule.trim();
|
|
@@ -5342,480 +5594,427 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5342
5594
|
action: "block"
|
|
5343
5595
|
}))
|
|
5344
5596
|
];
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
children: [
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Policy" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5376
|
-
className: "pf-muted",
|
|
5377
|
-
children: "Changes apply live"
|
|
5378
|
-
})]
|
|
5379
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5380
|
-
className: "pf-grid",
|
|
5597
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5598
|
+
className: "pf-section",
|
|
5599
|
+
children: [
|
|
5600
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5601
|
+
className: "pf-section-title",
|
|
5602
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Rules" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5603
|
+
className: "pf-muted",
|
|
5604
|
+
children: "Explicit rules; preset rules are applied in addition"
|
|
5605
|
+
})]
|
|
5606
|
+
}),
|
|
5607
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
5608
|
+
className: "pf-editor",
|
|
5609
|
+
onSubmit: addRule,
|
|
5610
|
+
children: [
|
|
5611
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5612
|
+
className: "pf-control",
|
|
5613
|
+
value: rule,
|
|
5614
|
+
disabled: !writable,
|
|
5615
|
+
placeholder: "plugin:example or announcement:*",
|
|
5616
|
+
onChange: (event) => {
|
|
5617
|
+
setRule(event.currentTarget.value);
|
|
5618
|
+
}
|
|
5619
|
+
}),
|
|
5620
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5621
|
+
className: "pf-control",
|
|
5622
|
+
value: ruleKind,
|
|
5623
|
+
disabled: !writable || ruleAction === "protect",
|
|
5624
|
+
onChange: (event) => {
|
|
5625
|
+
setRuleKind(event.currentTarget.value);
|
|
5626
|
+
},
|
|
5381
5627
|
children: [
|
|
5382
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
label: "Firewall enabled",
|
|
5386
|
-
hint: "Keep auditing available when policy is off.",
|
|
5387
|
-
onChange: (value) => {
|
|
5388
|
-
setPath(["enabled"], value);
|
|
5389
|
-
}
|
|
5390
|
-
}),
|
|
5391
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5392
|
-
checked: config?.protectCoreSections ?? true,
|
|
5393
|
-
disabled: !writable,
|
|
5394
|
-
label: "Protect core sections",
|
|
5395
|
-
hint: "Prevents ordinary rules from removing Harness internals.",
|
|
5396
|
-
onChange: (value) => {
|
|
5397
|
-
setPath(["protectCoreSections"], value);
|
|
5398
|
-
}
|
|
5628
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5629
|
+
value: "exact",
|
|
5630
|
+
children: "Exact"
|
|
5399
5631
|
}),
|
|
5400
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5401
|
-
|
|
5402
|
-
children:
|
|
5403
|
-
className: "pf-control",
|
|
5404
|
-
value: configuredMode,
|
|
5405
|
-
disabled: !writable,
|
|
5406
|
-
onChange: (event) => {
|
|
5407
|
-
setPath(["mode"], event.currentTarget.value);
|
|
5408
|
-
},
|
|
5409
|
-
children: [
|
|
5410
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5411
|
-
value: "off",
|
|
5412
|
-
children: "Off"
|
|
5413
|
-
}),
|
|
5414
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5415
|
-
value: "audit",
|
|
5416
|
-
children: "Audit only"
|
|
5417
|
-
}),
|
|
5418
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5419
|
-
value: "blocklist",
|
|
5420
|
-
children: "Blocklist"
|
|
5421
|
-
}),
|
|
5422
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5423
|
-
value: "allowlist",
|
|
5424
|
-
children: "Allowlist"
|
|
5425
|
-
})
|
|
5426
|
-
]
|
|
5427
|
-
})]
|
|
5428
|
-
}),
|
|
5429
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5430
|
-
className: "pf-field",
|
|
5431
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Preset" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5432
|
-
className: "pf-control",
|
|
5433
|
-
value: config?.preset ?? "",
|
|
5434
|
-
disabled: !writable,
|
|
5435
|
-
onChange: (event) => {
|
|
5436
|
-
const value = event.currentTarget.value;
|
|
5437
|
-
if (value === "") scope.unset("preset");
|
|
5438
|
-
else setPath(["preset"], value);
|
|
5439
|
-
},
|
|
5440
|
-
children: [
|
|
5441
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5442
|
-
value: "",
|
|
5443
|
-
children: "None"
|
|
5444
|
-
}),
|
|
5445
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5446
|
-
value: "clean",
|
|
5447
|
-
children: "Clean"
|
|
5448
|
-
}),
|
|
5449
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5450
|
-
value: "strict",
|
|
5451
|
-
children: "Strict"
|
|
5452
|
-
}),
|
|
5453
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5454
|
-
value: "audit-only",
|
|
5455
|
-
children: "Audit only"
|
|
5456
|
-
})
|
|
5457
|
-
]
|
|
5458
|
-
})]
|
|
5632
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5633
|
+
value: "prefix",
|
|
5634
|
+
children: "Prefix"
|
|
5459
5635
|
}),
|
|
5460
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5461
|
-
|
|
5462
|
-
children:
|
|
5463
|
-
className: "pf-control",
|
|
5464
|
-
value: config?.unknownPluginPolicy ?? "allow",
|
|
5465
|
-
disabled: !writable,
|
|
5466
|
-
onChange: (event) => {
|
|
5467
|
-
setPath(["unknownPluginPolicy"], event.currentTarget.value);
|
|
5468
|
-
},
|
|
5469
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5470
|
-
value: "allow",
|
|
5471
|
-
children: "Allow"
|
|
5472
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5473
|
-
value: "block",
|
|
5474
|
-
children: "Block"
|
|
5475
|
-
})]
|
|
5476
|
-
})]
|
|
5636
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5637
|
+
value: "glob",
|
|
5638
|
+
children: "Glob"
|
|
5477
5639
|
})
|
|
5478
5640
|
]
|
|
5479
|
-
})
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
refresh();
|
|
5490
|
-
},
|
|
5491
|
-
children: refreshing ? "Refreshing…" : "Refresh"
|
|
5492
|
-
})]
|
|
5493
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5494
|
-
className: "pf-stats",
|
|
5641
|
+
}),
|
|
5642
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5643
|
+
className: "pf-control",
|
|
5644
|
+
value: ruleAction,
|
|
5645
|
+
disabled: !writable,
|
|
5646
|
+
onChange: (event) => {
|
|
5647
|
+
const action = event.currentTarget.value;
|
|
5648
|
+
setRuleAction(action);
|
|
5649
|
+
if (action === "protect") setRuleKind("exact");
|
|
5650
|
+
},
|
|
5495
5651
|
children: [
|
|
5496
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5497
|
-
|
|
5498
|
-
children:
|
|
5499
|
-
}),
|
|
5500
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5501
|
-
className: "pf-stat",
|
|
5502
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: last?.blockedSections ?? "—" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "blocked" })]
|
|
5652
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5653
|
+
value: "block",
|
|
5654
|
+
children: "Block"
|
|
5503
5655
|
}),
|
|
5504
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5505
|
-
|
|
5506
|
-
children:
|
|
5656
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5657
|
+
value: "allow",
|
|
5658
|
+
children: "Allow"
|
|
5507
5659
|
}),
|
|
5508
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5509
|
-
|
|
5510
|
-
children:
|
|
5660
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5661
|
+
value: "protect",
|
|
5662
|
+
children: "Protect"
|
|
5511
5663
|
})
|
|
5512
5664
|
]
|
|
5665
|
+
}),
|
|
5666
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5667
|
+
className: "pf-btn primary",
|
|
5668
|
+
type: "submit",
|
|
5669
|
+
disabled: !writable || rule.trim().length === 0,
|
|
5670
|
+
children: "Add rule"
|
|
5671
|
+
})
|
|
5672
|
+
]
|
|
5673
|
+
}),
|
|
5674
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5675
|
+
className: "pf-rules",
|
|
5676
|
+
children: [explicitRules.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5677
|
+
className: "pf-empty",
|
|
5678
|
+
children: "No explicit rules yet."
|
|
5679
|
+
}), explicitRules.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5680
|
+
className: "pf-rule",
|
|
5681
|
+
children: [
|
|
5682
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
|
|
5683
|
+
title: item.value,
|
|
5684
|
+
children: item.value
|
|
5685
|
+
}),
|
|
5686
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5687
|
+
className: "pf-pill pf-kind",
|
|
5688
|
+
children: item.kind
|
|
5689
|
+
}),
|
|
5690
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5691
|
+
className: `pf-pill ${item.action}`,
|
|
5692
|
+
children: item.action
|
|
5693
|
+
}),
|
|
5694
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5695
|
+
className: "pf-btn link danger",
|
|
5696
|
+
disabled: !writable,
|
|
5697
|
+
onClick: () => {
|
|
5698
|
+
setPath([item.field], list(config, item.field).filter((value) => value !== item.value));
|
|
5699
|
+
},
|
|
5700
|
+
children: "Remove"
|
|
5701
|
+
})
|
|
5702
|
+
]
|
|
5703
|
+
}, `${item.field}:${item.value}`))]
|
|
5704
|
+
})
|
|
5705
|
+
]
|
|
5706
|
+
});
|
|
5707
|
+
}
|
|
5708
|
+
function AuditSection(props) {
|
|
5709
|
+
const { config, writable, setPath } = props;
|
|
5710
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
5711
|
+
className: "pf-advanced",
|
|
5712
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "Audit & metrics" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5713
|
+
className: "pf-advanced-content pf-grid",
|
|
5714
|
+
children: [
|
|
5715
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5716
|
+
checked: config?.audit?.enabled ?? true,
|
|
5717
|
+
disabled: !writable,
|
|
5718
|
+
label: "Audit history",
|
|
5719
|
+
hint: "Keep recent assemblies in Host memory.",
|
|
5720
|
+
onChange: (value) => {
|
|
5721
|
+
setPath(["audit", "enabled"], value);
|
|
5722
|
+
}
|
|
5723
|
+
}),
|
|
5724
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5725
|
+
checked: config?.audit?.includePreview ?? false,
|
|
5726
|
+
disabled: !writable,
|
|
5727
|
+
label: "Section preview",
|
|
5728
|
+
hint: "Expose only the configured prefix in Inspector.",
|
|
5729
|
+
onChange: (value) => {
|
|
5730
|
+
setPath(["audit", "includePreview"], value);
|
|
5731
|
+
}
|
|
5732
|
+
}),
|
|
5733
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5734
|
+
checked: config?.audit?.logBlocked ?? true,
|
|
5735
|
+
disabled: !writable,
|
|
5736
|
+
label: "Log blocked sections",
|
|
5737
|
+
hint: "Names and sizes only unless preview is enabled.",
|
|
5738
|
+
onChange: (value) => {
|
|
5739
|
+
setPath(["audit", "logBlocked"], value);
|
|
5740
|
+
}
|
|
5741
|
+
}),
|
|
5742
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5743
|
+
checked: config?.audit?.logAllowed ?? false,
|
|
5744
|
+
disabled: !writable,
|
|
5745
|
+
label: "Log allowed sections",
|
|
5746
|
+
hint: "Useful for initial policy discovery.",
|
|
5747
|
+
onChange: (value) => {
|
|
5748
|
+
setPath(["audit", "logAllowed"], value);
|
|
5749
|
+
}
|
|
5750
|
+
}),
|
|
5751
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5752
|
+
checked: config?.audit?.highlightNewSections ?? true,
|
|
5753
|
+
disabled: !writable,
|
|
5754
|
+
label: "Highlight new plugin sections",
|
|
5755
|
+
hint: "Informational only; never blocks automatically.",
|
|
5756
|
+
onChange: (value) => {
|
|
5757
|
+
setPath(["audit", "highlightNewSections"], value);
|
|
5758
|
+
}
|
|
5759
|
+
}),
|
|
5760
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5761
|
+
checked: config?.metrics?.enabled ?? true,
|
|
5762
|
+
disabled: !writable,
|
|
5763
|
+
label: "Aggregate metrics",
|
|
5764
|
+
hint: "No arbitrary section-name labels.",
|
|
5765
|
+
onChange: (value) => {
|
|
5766
|
+
setPath(["metrics", "enabled"], value);
|
|
5767
|
+
}
|
|
5768
|
+
}),
|
|
5769
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5770
|
+
className: "pf-field",
|
|
5771
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Preview characters" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5772
|
+
className: "pf-control",
|
|
5773
|
+
type: "number",
|
|
5774
|
+
min: "0",
|
|
5775
|
+
step: "1",
|
|
5776
|
+
value: config?.audit?.previewChars ?? 160,
|
|
5777
|
+
disabled: !writable,
|
|
5778
|
+
onChange: (event) => {
|
|
5779
|
+
setPath(["audit", "previewChars"], Number(event.currentTarget.value));
|
|
5780
|
+
}
|
|
5513
5781
|
})]
|
|
5514
5782
|
}),
|
|
5515
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("
|
|
5516
|
-
className: "pf-
|
|
5517
|
-
children: [
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5783
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5784
|
+
className: "pf-field",
|
|
5785
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "History size" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5786
|
+
className: "pf-control",
|
|
5787
|
+
type: "number",
|
|
5788
|
+
min: "0",
|
|
5789
|
+
step: "1",
|
|
5790
|
+
value: config?.audit?.historySize ?? 100,
|
|
5791
|
+
disabled: !writable,
|
|
5792
|
+
onChange: (event) => {
|
|
5793
|
+
setPath(["audit", "historySize"], Number(event.currentTarget.value));
|
|
5794
|
+
}
|
|
5795
|
+
})]
|
|
5796
|
+
})
|
|
5797
|
+
]
|
|
5798
|
+
})]
|
|
5799
|
+
});
|
|
5800
|
+
}
|
|
5801
|
+
function InspectorSection(props) {
|
|
5802
|
+
const last = props.inspector?.last ?? null;
|
|
5803
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5804
|
+
className: "pf-section",
|
|
5805
|
+
children: [
|
|
5806
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5807
|
+
className: "pf-section-title",
|
|
5808
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Prompt Inspector" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5809
|
+
className: "pf-muted",
|
|
5810
|
+
children: "Updates every 3 seconds"
|
|
5811
|
+
})]
|
|
5812
|
+
}),
|
|
5813
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5814
|
+
className: "pf-table-wrap",
|
|
5815
|
+
children: last === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5816
|
+
className: "pf-empty",
|
|
5817
|
+
children: "No audited prompt assembly yet."
|
|
5818
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
5819
|
+
className: "pf-table",
|
|
5820
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5821
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Section" }),
|
|
5822
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Size" }),
|
|
5823
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Decision" }),
|
|
5824
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Reason" }),
|
|
5825
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Policy" })
|
|
5826
|
+
] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: last.sections.map((section, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5827
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5828
|
+
className: "pf-section-name",
|
|
5829
|
+
children: [
|
|
5830
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: section.name }),
|
|
5831
|
+
section.isNew && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5832
|
+
className: "pf-new",
|
|
5833
|
+
children: "NEW"
|
|
5834
|
+
}),
|
|
5835
|
+
section.suspicious && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5836
|
+
className: "pf-warn",
|
|
5837
|
+
children: "POSSIBLE ANNOUNCEMENT"
|
|
5838
|
+
})
|
|
5839
|
+
]
|
|
5840
|
+
}), section.preview !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5841
|
+
className: "pf-preview",
|
|
5842
|
+
children: section.preview
|
|
5843
|
+
})] }),
|
|
5844
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", { children: [
|
|
5845
|
+
"~",
|
|
5846
|
+
section.estimatedTokens,
|
|
5847
|
+
" t",
|
|
5848
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
|
|
5849
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5521
5850
|
className: "pf-muted",
|
|
5522
|
-
children: "
|
|
5523
|
-
})
|
|
5524
|
-
}),
|
|
5525
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5526
|
-
className:
|
|
5527
|
-
|
|
5851
|
+
children: [section.chars, " chars"]
|
|
5852
|
+
})
|
|
5853
|
+
] }),
|
|
5854
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5855
|
+
className: `pf-pill ${section.decision === "blocked" ? "block" : section.decision === "protected" ? "protect" : "allow"}`,
|
|
5856
|
+
children: section.decision
|
|
5857
|
+
}) }),
|
|
5858
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: section.reason }),
|
|
5859
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5860
|
+
className: "pf-actions",
|
|
5528
5861
|
children: [
|
|
5529
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
5530
|
-
className: "pf-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
}
|
|
5862
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5863
|
+
className: "pf-btn link",
|
|
5864
|
+
disabled: !props.writable,
|
|
5865
|
+
onClick: () => {
|
|
5866
|
+
props.setPolicy(section.name, "allow");
|
|
5867
|
+
},
|
|
5868
|
+
children: "Allow"
|
|
5537
5869
|
}),
|
|
5538
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5539
|
-
className: "pf-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
setRuleKind(event.currentTarget.value);
|
|
5870
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5871
|
+
className: "pf-btn link danger",
|
|
5872
|
+
disabled: !props.writable,
|
|
5873
|
+
onClick: () => {
|
|
5874
|
+
props.setPolicy(section.name, "block");
|
|
5544
5875
|
},
|
|
5545
|
-
children:
|
|
5546
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5547
|
-
value: "exact",
|
|
5548
|
-
children: "Exact"
|
|
5549
|
-
}),
|
|
5550
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5551
|
-
value: "prefix",
|
|
5552
|
-
children: "Prefix"
|
|
5553
|
-
}),
|
|
5554
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5555
|
-
value: "glob",
|
|
5556
|
-
children: "Glob"
|
|
5557
|
-
})
|
|
5558
|
-
]
|
|
5876
|
+
children: "Block"
|
|
5559
5877
|
}),
|
|
5560
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5561
|
-
className: "pf-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
const action = event.currentTarget.value;
|
|
5566
|
-
setRuleAction(action);
|
|
5567
|
-
if (action === "protect") setRuleKind("exact");
|
|
5878
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5879
|
+
className: "pf-btn link",
|
|
5880
|
+
disabled: !props.writable,
|
|
5881
|
+
onClick: () => {
|
|
5882
|
+
props.setPolicy(section.name, "protect");
|
|
5568
5883
|
},
|
|
5569
|
-
children:
|
|
5570
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5571
|
-
value: "block",
|
|
5572
|
-
children: "Block"
|
|
5573
|
-
}),
|
|
5574
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5575
|
-
value: "allow",
|
|
5576
|
-
children: "Allow"
|
|
5577
|
-
}),
|
|
5578
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5579
|
-
value: "protect",
|
|
5580
|
-
children: "Protect"
|
|
5581
|
-
})
|
|
5582
|
-
]
|
|
5884
|
+
children: "Protect"
|
|
5583
5885
|
}),
|
|
5584
5886
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5585
|
-
className: "pf-btn
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5887
|
+
className: "pf-btn link",
|
|
5888
|
+
disabled: !props.writable,
|
|
5889
|
+
onClick: () => {
|
|
5890
|
+
props.setPolicy(section.name, "clear");
|
|
5891
|
+
},
|
|
5892
|
+
children: "Clear"
|
|
5589
5893
|
})
|
|
5590
5894
|
]
|
|
5591
|
-
})
|
|
5592
|
-
|
|
5593
|
-
className: "pf-rules",
|
|
5594
|
-
children: [explicitRules.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5595
|
-
className: "pf-empty",
|
|
5596
|
-
children: "No explicit rules yet."
|
|
5597
|
-
}), explicitRules.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5598
|
-
className: "pf-rule",
|
|
5599
|
-
children: [
|
|
5600
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
|
|
5601
|
-
title: item.value,
|
|
5602
|
-
children: item.value
|
|
5603
|
-
}),
|
|
5604
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5605
|
-
className: "pf-pill pf-kind",
|
|
5606
|
-
children: item.kind
|
|
5607
|
-
}),
|
|
5608
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5609
|
-
className: `pf-pill ${item.action}`,
|
|
5610
|
-
children: item.action
|
|
5611
|
-
}),
|
|
5612
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5613
|
-
className: "pf-btn link danger",
|
|
5614
|
-
disabled: !writable,
|
|
5615
|
-
onClick: () => {
|
|
5616
|
-
setPath([item.field], list(config, item.field).filter((value) => value !== item.value));
|
|
5617
|
-
},
|
|
5618
|
-
children: "Remove"
|
|
5619
|
-
})
|
|
5620
|
-
]
|
|
5621
|
-
}, `${item.field}:${item.value}`))]
|
|
5622
|
-
})
|
|
5623
|
-
]
|
|
5624
|
-
}),
|
|
5625
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
5626
|
-
className: "pf-advanced",
|
|
5627
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "Audit & metrics" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5628
|
-
className: "pf-advanced-content pf-grid",
|
|
5629
|
-
children: [
|
|
5630
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5631
|
-
checked: config?.audit?.enabled ?? true,
|
|
5632
|
-
disabled: !writable,
|
|
5633
|
-
label: "Audit history",
|
|
5634
|
-
hint: "Keep recent assemblies in Host memory.",
|
|
5635
|
-
onChange: (value) => {
|
|
5636
|
-
setPath(["audit", "enabled"], value);
|
|
5637
|
-
}
|
|
5638
|
-
}),
|
|
5639
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5640
|
-
checked: config?.audit?.includePreview ?? false,
|
|
5641
|
-
disabled: !writable,
|
|
5642
|
-
label: "Section preview",
|
|
5643
|
-
hint: "Expose only the configured prefix in Inspector.",
|
|
5644
|
-
onChange: (value) => {
|
|
5645
|
-
setPath(["audit", "includePreview"], value);
|
|
5646
|
-
}
|
|
5647
|
-
}),
|
|
5648
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5649
|
-
checked: config?.audit?.logBlocked ?? true,
|
|
5650
|
-
disabled: !writable,
|
|
5651
|
-
label: "Log blocked sections",
|
|
5652
|
-
hint: "Names and sizes only unless preview is enabled.",
|
|
5653
|
-
onChange: (value) => {
|
|
5654
|
-
setPath(["audit", "logBlocked"], value);
|
|
5655
|
-
}
|
|
5656
|
-
}),
|
|
5657
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5658
|
-
checked: config?.audit?.logAllowed ?? false,
|
|
5659
|
-
disabled: !writable,
|
|
5660
|
-
label: "Log allowed sections",
|
|
5661
|
-
hint: "Useful for initial policy discovery.",
|
|
5662
|
-
onChange: (value) => {
|
|
5663
|
-
setPath(["audit", "logAllowed"], value);
|
|
5664
|
-
}
|
|
5665
|
-
}),
|
|
5666
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5667
|
-
checked: config?.audit?.highlightNewSections ?? true,
|
|
5668
|
-
disabled: !writable,
|
|
5669
|
-
label: "Highlight new plugin sections",
|
|
5670
|
-
hint: "Informational only; never blocks automatically.",
|
|
5671
|
-
onChange: (value) => {
|
|
5672
|
-
setPath(["audit", "highlightNewSections"], value);
|
|
5673
|
-
}
|
|
5674
|
-
}),
|
|
5675
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5676
|
-
checked: config?.metrics?.enabled ?? true,
|
|
5677
|
-
disabled: !writable,
|
|
5678
|
-
label: "Aggregate metrics",
|
|
5679
|
-
hint: "No arbitrary section-name labels.",
|
|
5680
|
-
onChange: (value) => {
|
|
5681
|
-
setPath(["metrics", "enabled"], value);
|
|
5682
|
-
}
|
|
5683
|
-
}),
|
|
5684
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5685
|
-
className: "pf-field",
|
|
5686
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Preview characters" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5687
|
-
className: "pf-control",
|
|
5688
|
-
type: "number",
|
|
5689
|
-
min: "0",
|
|
5690
|
-
step: "1",
|
|
5691
|
-
value: config?.audit?.previewChars ?? 160,
|
|
5692
|
-
disabled: !writable,
|
|
5693
|
-
onChange: (event) => {
|
|
5694
|
-
setPath(["audit", "previewChars"], Number(event.currentTarget.value));
|
|
5695
|
-
}
|
|
5696
|
-
})]
|
|
5697
|
-
}),
|
|
5698
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5699
|
-
className: "pf-field",
|
|
5700
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "History size" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5701
|
-
className: "pf-control",
|
|
5702
|
-
type: "number",
|
|
5703
|
-
min: "0",
|
|
5704
|
-
step: "1",
|
|
5705
|
-
value: config?.audit?.historySize ?? 100,
|
|
5706
|
-
disabled: !writable,
|
|
5707
|
-
onChange: (event) => {
|
|
5708
|
-
setPath(["audit", "historySize"], Number(event.currentTarget.value));
|
|
5709
|
-
}
|
|
5710
|
-
})]
|
|
5711
|
-
})
|
|
5712
|
-
]
|
|
5713
|
-
})]
|
|
5714
|
-
}),
|
|
5715
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5716
|
-
className: "pf-section",
|
|
5717
|
-
children: [
|
|
5718
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5719
|
-
className: "pf-section-title",
|
|
5720
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Prompt Inspector" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5721
|
-
className: "pf-muted",
|
|
5722
|
-
children: "Updates every 3 seconds"
|
|
5723
|
-
})]
|
|
5724
|
-
}),
|
|
5725
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5726
|
-
className: "pf-table-wrap",
|
|
5727
|
-
children: last === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5728
|
-
className: "pf-empty",
|
|
5729
|
-
children: "No audited prompt assembly yet."
|
|
5730
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
5731
|
-
className: "pf-table",
|
|
5732
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5733
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Section" }),
|
|
5734
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Size" }),
|
|
5735
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Decision" }),
|
|
5736
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Reason" }),
|
|
5737
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Policy" })
|
|
5738
|
-
] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: last.sections.map((section, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5739
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5740
|
-
className: "pf-section-name",
|
|
5741
|
-
children: [
|
|
5742
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: section.name }),
|
|
5743
|
-
section.isNew && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5744
|
-
className: "pf-new",
|
|
5745
|
-
children: "NEW"
|
|
5746
|
-
}),
|
|
5747
|
-
section.suspicious && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5748
|
-
className: "pf-warn",
|
|
5749
|
-
children: "POSSIBLE ANNOUNCEMENT"
|
|
5750
|
-
})
|
|
5751
|
-
]
|
|
5752
|
-
}), section.preview !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5753
|
-
className: "pf-preview",
|
|
5754
|
-
children: section.preview
|
|
5755
|
-
})] }),
|
|
5756
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", { children: [
|
|
5757
|
-
"~",
|
|
5758
|
-
section.estimatedTokens,
|
|
5759
|
-
" t",
|
|
5760
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
|
|
5761
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5762
|
-
className: "pf-muted",
|
|
5763
|
-
children: [section.chars, " chars"]
|
|
5764
|
-
})
|
|
5765
|
-
] }),
|
|
5766
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5767
|
-
className: `pf-pill ${section.decision === "blocked" ? "block" : section.decision === "protected" ? "protect" : "allow"}`,
|
|
5768
|
-
children: section.decision
|
|
5769
|
-
}) }),
|
|
5770
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: section.reason }),
|
|
5771
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5772
|
-
className: "pf-actions",
|
|
5773
|
-
children: [
|
|
5774
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5775
|
-
className: "pf-btn link",
|
|
5776
|
-
disabled: !writable,
|
|
5777
|
-
onClick: () => {
|
|
5778
|
-
setPolicy(section.name, "allow");
|
|
5779
|
-
},
|
|
5780
|
-
children: "Allow"
|
|
5781
|
-
}),
|
|
5782
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5783
|
-
className: "pf-btn link danger",
|
|
5784
|
-
disabled: !writable,
|
|
5785
|
-
onClick: () => {
|
|
5786
|
-
setPolicy(section.name, "block");
|
|
5787
|
-
},
|
|
5788
|
-
children: "Block"
|
|
5789
|
-
}),
|
|
5790
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5791
|
-
className: "pf-btn link",
|
|
5792
|
-
disabled: !writable,
|
|
5793
|
-
onClick: () => {
|
|
5794
|
-
setPolicy(section.name, "protect");
|
|
5795
|
-
},
|
|
5796
|
-
children: "Protect"
|
|
5797
|
-
}),
|
|
5798
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5799
|
-
className: "pf-btn link",
|
|
5800
|
-
disabled: !writable,
|
|
5801
|
-
onClick: () => {
|
|
5802
|
-
setPolicy(section.name, "clear");
|
|
5803
|
-
},
|
|
5804
|
-
children: "Clear"
|
|
5805
|
-
})
|
|
5806
|
-
]
|
|
5807
|
-
}) })
|
|
5808
|
-
] }, `${section.name}:${index}`)) })]
|
|
5809
|
-
})
|
|
5810
|
-
}),
|
|
5811
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5812
|
-
className: "pf-footer-note",
|
|
5813
|
-
children: "Token counts are estimates. Prompt Firewall is a hygiene and observability layer, not a security boundary."
|
|
5814
|
-
})
|
|
5815
|
-
]
|
|
5895
|
+
}) })
|
|
5896
|
+
] }, `${section.name}:${index}`)) })]
|
|
5816
5897
|
})
|
|
5817
|
-
|
|
5818
|
-
|
|
5898
|
+
}),
|
|
5899
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5900
|
+
className: "pf-footer-note",
|
|
5901
|
+
children: "Token counts are estimates. Prompt Firewall is a hygiene and observability layer, not a security boundary."
|
|
5902
|
+
})
|
|
5903
|
+
]
|
|
5904
|
+
});
|
|
5905
|
+
}
|
|
5906
|
+
//#endregion
|
|
5907
|
+
//#region src/client/index.tsx
|
|
5908
|
+
const SETTINGS_NAMESPACE = "prompt-firewall";
|
|
5909
|
+
const REFRESH_INTERVAL_MS = 3e3;
|
|
5910
|
+
function displayError(error) {
|
|
5911
|
+
if (error instanceof Error) return error.message;
|
|
5912
|
+
if (typeof error === "string") return error;
|
|
5913
|
+
return "Could not load Prompt Inspector data.";
|
|
5914
|
+
}
|
|
5915
|
+
function PromptFirewallCard({ scope, inspect, setSectionPolicy }) {
|
|
5916
|
+
const settingsStore = (0, react.useMemo)(() => bindSettingsExternalStore(scope), [scope]);
|
|
5917
|
+
const settings = (0, react.useSyncExternalStore)(settingsStore.subscribe, settingsStore.getSnapshot, settingsStore.getSnapshot);
|
|
5918
|
+
const config = settings.value;
|
|
5919
|
+
const writable = settings.status === "ready" && settings.writable;
|
|
5920
|
+
const [inspector, setInspector] = (0, react.useState)(null);
|
|
5921
|
+
const [error, setError] = (0, react.useState)(null);
|
|
5922
|
+
const [refreshing, setRefreshing] = (0, react.useState)(false);
|
|
5923
|
+
const activeRequest = (0, react.useRef)(0);
|
|
5924
|
+
const refresh = (0, react.useCallback)(async () => {
|
|
5925
|
+
const request = ++activeRequest.current;
|
|
5926
|
+
setRefreshing(true);
|
|
5927
|
+
try {
|
|
5928
|
+
const result = await inspect();
|
|
5929
|
+
if (request !== activeRequest.current) return;
|
|
5930
|
+
if (result.ok) {
|
|
5931
|
+
setInspector(result.value);
|
|
5932
|
+
setError(null);
|
|
5933
|
+
} else setError(displayError(result.error));
|
|
5934
|
+
} catch (cause) {
|
|
5935
|
+
if (request === activeRequest.current) setError(displayError(cause));
|
|
5936
|
+
} finally {
|
|
5937
|
+
if (request === activeRequest.current) setRefreshing(false);
|
|
5938
|
+
}
|
|
5939
|
+
}, [inspect]);
|
|
5940
|
+
(0, react.useEffect)(() => {
|
|
5941
|
+
const stopPolling = startVisibilityAwarePolling(refresh, REFRESH_INTERVAL_MS);
|
|
5942
|
+
return () => {
|
|
5943
|
+
stopPolling();
|
|
5944
|
+
activeRequest.current += 1;
|
|
5945
|
+
};
|
|
5946
|
+
}, [refresh]);
|
|
5947
|
+
const setPath = (0, react.useCallback)((path, value) => {
|
|
5948
|
+
const [field, nested] = path;
|
|
5949
|
+
if (field === void 0) return;
|
|
5950
|
+
if (nested === void 0) {
|
|
5951
|
+
scope.set(field, value);
|
|
5952
|
+
return;
|
|
5953
|
+
}
|
|
5954
|
+
const current = scope.getSnapshot().value;
|
|
5955
|
+
const parent = field === "audit" ? current?.audit : current?.metrics;
|
|
5956
|
+
scope.set(field, {
|
|
5957
|
+
...parent,
|
|
5958
|
+
[nested]: value
|
|
5959
|
+
});
|
|
5960
|
+
}, [scope]);
|
|
5961
|
+
const setPolicy = (0, react.useCallback)(async (name, policy) => {
|
|
5962
|
+
const result = await setSectionPolicy(name, policy, scope.getSnapshot().revision);
|
|
5963
|
+
if (!result.ok) setError(displayError(result.error));
|
|
5964
|
+
await refresh();
|
|
5965
|
+
}, [
|
|
5966
|
+
refresh,
|
|
5967
|
+
scope,
|
|
5968
|
+
setSectionPolicy
|
|
5969
|
+
]);
|
|
5970
|
+
const enabled = config?.enabled ?? true;
|
|
5971
|
+
if (settings.status === "unavailable") return null;
|
|
5972
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CardShell, {
|
|
5973
|
+
title: "Prompt Firewall",
|
|
5974
|
+
description: "Prompt hygiene, section policy, and request-level observability.",
|
|
5975
|
+
badge: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5976
|
+
className: "dsh-plugin-card__badge",
|
|
5977
|
+
children: enabled ? "Enabled" : "Disabled"
|
|
5978
|
+
}),
|
|
5979
|
+
label: (open) => `${open ? "Hide" : "Show"} settings: Prompt Firewall`,
|
|
5980
|
+
bodyClassName: "pf-body",
|
|
5981
|
+
children: [
|
|
5982
|
+
error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5983
|
+
className: "pf-error",
|
|
5984
|
+
children: error
|
|
5985
|
+
}),
|
|
5986
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PolicySection, {
|
|
5987
|
+
config,
|
|
5988
|
+
writable,
|
|
5989
|
+
setPath,
|
|
5990
|
+
unsetPreset: () => {
|
|
5991
|
+
scope.unset("preset");
|
|
5992
|
+
}
|
|
5993
|
+
}),
|
|
5994
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(LastRequestSection, {
|
|
5995
|
+
config,
|
|
5996
|
+
inspector,
|
|
5997
|
+
refreshing,
|
|
5998
|
+
onRefresh: () => {
|
|
5999
|
+
refresh();
|
|
6000
|
+
}
|
|
6001
|
+
}),
|
|
6002
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RulesSection, {
|
|
6003
|
+
config,
|
|
6004
|
+
writable,
|
|
6005
|
+
setPath
|
|
6006
|
+
}),
|
|
6007
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AuditSection, {
|
|
6008
|
+
config,
|
|
6009
|
+
writable,
|
|
6010
|
+
setPath
|
|
6011
|
+
}),
|
|
6012
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InspectorSection, {
|
|
6013
|
+
inspector,
|
|
6014
|
+
writable,
|
|
6015
|
+
setPolicy
|
|
6016
|
+
})
|
|
6017
|
+
]
|
|
5819
6018
|
});
|
|
5820
6019
|
}
|
|
5821
6020
|
const inject = [
|
|
@@ -5825,27 +6024,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5825
6024
|
];
|
|
5826
6025
|
/** Mount the generated Remote contribution and register the native Settings card. */
|
|
5827
6026
|
async function apply(ctx) {
|
|
5828
|
-
const
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
style.remove();
|
|
6027
|
+
const disposeRemote = await ctx.remote.$mount(TYPERT_REMOTE);
|
|
6028
|
+
try {
|
|
6029
|
+
await ctx.inject(["remote.promptFirewall"], (remoteCtx) => {
|
|
6030
|
+
const injectedRemote = remoteCtx.remote;
|
|
6031
|
+
const face = {
|
|
6032
|
+
scope: remoteCtx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE }),
|
|
6033
|
+
inspect: () => injectedRemote.promptFirewall.inspect(),
|
|
6034
|
+
setSectionPolicy: (section, policy, revision) => injectedRemote.promptFirewall.setSectionPolicy(section, policy, revision)
|
|
6035
|
+
};
|
|
6036
|
+
return registerSettingsCard(remoteCtx, {
|
|
6037
|
+
key: SETTINGS_NAMESPACE,
|
|
6038
|
+
pluginName: "dsh-prompt-firewall",
|
|
6039
|
+
styles,
|
|
6040
|
+
component: PromptFirewallCard,
|
|
6041
|
+
inject: () => face
|
|
6042
|
+
});
|
|
6043
|
+
});
|
|
6044
|
+
} catch (cause) {
|
|
5847
6045
|
await disposeRemote();
|
|
5848
|
-
|
|
6046
|
+
throw cause;
|
|
6047
|
+
}
|
|
6048
|
+
return disposeRemote;
|
|
5849
6049
|
}
|
|
5850
6050
|
//#endregion
|
|
5851
6051
|
exports.apply = apply;
|