Feat v0.3.7 package audit (#20)
All checks were successful
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-frontend (push) Successful in 6s
CI/CD / test-go-pg (push) Successful in 2m36s
CI/CD / test-sqlite (push) Successful in 2m41s
CI/CD / build-and-deploy (push) Successful in 1m13s

Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #20.
This commit is contained in:
2026-03-28 21:22:39 +00:00
committed by xcaliber
parent d68451fe8e
commit d91ec02dd7
47 changed files with 2067 additions and 53 deletions

View File

@@ -27,6 +27,11 @@ function sourceBadge(source) {
return html`<span class="badge ${cls}">${source}</span>`;
}
function statusBadge(status) {
if (status === 'dormant') return html`<span class="badge" style="opacity:0.6;">dormant</span>`;
return null;
}
export default function PackagesSection() {
const [packages, setPackages] = useState([]);
const [loading, setLoading] = useState(true);
@@ -56,6 +61,10 @@ export default function PackagesSection() {
// ── Actions ─────────────────────────────────
async function toggleEnabled(pkg) {
if (CORE_IDS.has(pkg.id)) return;
if (pkg.status === 'dormant') {
sw.toast('This package requires chat — it cannot be enabled yet', 'error');
return;
}
try {
if (pkg.enabled) {
await sw.api.admin.packages.disable(pkg.id);
@@ -154,6 +163,7 @@ export default function PackagesSection() {
if (loading) return html`<div class="settings-placeholder">Loading\u2026</div>`;
const enabled = packages.filter(p => p.enabled).length;
const dormant = packages.filter(p => p.status === 'dormant').length;
const hasManifestSettings = (pkg) =>
pkg.manifest?.settings || pkg.package_settings;
@@ -163,6 +173,7 @@ export default function PackagesSection() {
<div class="stat-cards-grid" style="margin-bottom:16px;">
<div class="stat-card"><div class="stat-value">${packages.length}</div><div class="stat-label">Total</div></div>
<div class="stat-card"><div class="stat-value">${enabled}</div><div class="stat-label">Enabled</div></div>
${dormant > 0 && html`<div class="stat-card"><div class="stat-value">${dormant}</div><div class="stat-label">Dormant</div></div>`}
</div>
${/* ── Action bar ─────────────── */``}
@@ -194,12 +205,14 @@ export default function PackagesSection() {
${' '}${typeBadge(pkg.type)}
${' '}${tierBadge(pkg.tier)}
${sourceBadge(pkg.source)}
${statusBadge(pkg.status)}
${pkg.is_system && html`<span class="badge" style="margin-left:4px;">system</span>`}
</div>
<div class="admin-actions-cell">
<button class="btn-small"
onClick=${() => toggleEnabled(pkg)}
disabled=${CORE_IDS.has(pkg.id)}>
disabled=${CORE_IDS.has(pkg.id) || pkg.status === 'dormant'}
title=${pkg.status === 'dormant' ? 'Requires chat' : ''}>
${pkg.enabled ? 'Disable' : 'Enable'}
</button>
${hasManifestSettings(pkg) && html`

View File

@@ -15,8 +15,10 @@ export default function TeamsSection() {
const loadTeams = useCallback(async () => {
try {
const data = await sw.api.admin.teams.list();
setTeams(data || []);
const resp = await sw.api.admin.teams.list();
// Paginated response: { data: [...], total, page }
const list = Array.isArray(resp) ? resp : (resp && resp.data ? resp.data : []);
setTeams(list);
} catch (e) { sw.toast(e.message, 'error'); }
finally { setLoading(false); }
}, []);