${s.label}
${rule.tool_pattern}
${rule.priority}
${has(rule.path_pattern) ? html`
${rule.path_pattern}
` : ''}
${has(rule.source) ? html`${rule.source}` : ''}
${has(rule.agent_id) ? html`${rule.agent_id}` : ''}
${has(rule.note) ? html`${rule.note}` : ''}
`;
}
// ── 4-state chip group ────────────────────────────────────────────────────────
_renderChipGroup(currentAction, onChange) {
const chips = [
{ action: null, label: '—' },
{ action: 'allow', label: 'Allow' },
{ action: 'require', label: 'Req' },
{ action: 'deny', label: 'Deny' },
];
return html`
${chips.map(({ action, label }) => {
const isActive = currentAction === action;
return html`
`;
})}
`;
}
// ── Tool row ─────────────────────────────────────────────────────────────────
_renderToolRow(tool) {
const action = this._getToolAction(tool.name);
const saving = this._toolSaving.has(tool.name);
return html`
${isOpen ? html`
${rules.length === 0
? html`
No path rules yet — add one below.
`
: rules.map(r => this._renderFsRow(r))}
${this._renderFsAddRow()}
Default unmatched paths
${this._renderFsAccessSelect(defValue, (v) => this._setFsDefault(v), true)}
` : nothing}
`;
}
// ── Side panel (Override / LowPrio) ──────────────────────────────────────────
_renderSidePanel(panelKey, title, icon, subtitle, rules, isOpen, onToggle, onAdd) {
const formActive = this._editingId !== null && this._formMode === panelKey;
return html`
Default action
if no rule matches
${this._renderChipGroup(action, (a) => this._setDefaultAction(a))}
${action === null
? html`
system default: allow`
: nothing}
`;
}
// ── Rules view ────────────────────────────────────────────────────────────────
render() {
if (!this._selectedGroup) return nothing;
const group = this._selectedGroup;
const isDefault = group.id === 'default';
const { overrides, lowPrio } = this._buckets(group.id);
const totalRules = this._rulesForGroup(group.id).length;
return html`
${this._error ? html`
${this._error}
` : nothing}
${this._renderSidePanel(
'override',
'Overrides',
'bi-exclamation-triangle-fill',
'priority < 0 · evaluated first',
overrides,
this._overrideOpen,
() => { this._overrideOpen = !this._overrideOpen; },
() => this._startNew('override')
)}
${this._renderFsPanel()}
${this._renderToolMatrix()}
${this._renderSidePanel(
'lowprio',
'Low Priority',
'bi-arrow-down-circle-fill',
'priority 1–999998 · evaluated after per-tool',
lowPrio,
this._lowPrioOpen,
() => { this._lowPrioOpen = !this._lowPrioOpen; },
() => this._startNew('lowprio')
)}
${this._renderDefaultActionBar()}
`;
}
}