Skip to content

feat(audit-log): dashboard audit log system with slideover UI#144

Open
Copilot wants to merge 46 commits into
mainfrom
copilot/create-log-system-for-changes
Open

feat(audit-log): dashboard audit log system with slideover UI#144
Copilot wants to merge 46 commits into
mainfrom
copilot/create-log-system-for-changes

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 11, 2026

Linked issue

Context

The dashboard had no way to see what changed in guild settings, who ran commands, or review past moderation actions. This adds a /guilds/:id/logs page with tabs for each log type, and wires up the evlog hash-chain audit pipeline so settings changes are persisted and verifiable.

The evlog infrastructure was folded in here since both features write to the same AuditEvent table.

Description

Database

  • Added AuditEvent model with SHA-256 hash chain (AuditChainHead stores the chain tip)
  • Added CommandLog model (non-chained; written directly by the bot via shared Postgres)
  • Added raw SQL partial indexes on Moderation.createdAt (nullable column — cannot use Prisma @@index)

Server

  • server/api/guilds/[guild]/logs/index.get.ts — dashboard activity feed (reads AuditEvent filtered to dashboard actions for the guild)
  • server/api/guilds/[guild]/logs/moderation.get.ts — moderation cases with pagination and type filtering
  • server/api/guilds/[guild]/logs/commands.get.ts — command execution history
  • server/api/guilds/[guild]/settings.patch.ts — updated to call log.audit() on settings saves, capturing a before/after diff
  • server/plugins/evlog-drain.ts + server/utils/audit/postgres-drain.ts — Postgres sink with serializable transaction, 5x retry on write conflicts, swallows duplicate-key errors
  • server/plugins/evlog-enrich.ts — enriches every event with request UA and tenantId (guild id)

Shared

  • shared/audit/actions.ts — typed action creators (guildSettingsUpdate, userLogin, etc.)
  • shared/audit/envelope.ts — canonical envelope shape + hashEnvelope() used by both the drain and the verify script
  • shared/types/audit-log.ts, command-log.ts, moderation-log.ts, moderation-types.ts — DTO types
  • shared/schemas — valibot schemas with transform(Number) coercion for query string params

Frontend

  • app/pages/(app)/guilds/[...id]/logs.vue — new logs page, tab-based (moderation, commands, activity)
  • app/components/guild/logs/ModerationLogTable.vue, CommandLogTable.vue, DashboardActivityTable.vue — table components with search, pagination, and loading states
  • app/utils/audit-log.ts — formatting helpers for change diffs (roles, channels, durations, arrays)
  • app/components/ActivitySection.vue — quick-preview widget in the manage navbar (deep-links to the activity tab)

Scripts

  • scripts/audit-verify.ts — offline hash-chain replay tool (pnpm audit:verify) to detect tampering

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 11, 2026

Deploy Preview for wolfstar-rocks-et34281 ready!

Name Link
🔨 Latest commit 94a3d8d
🔍 Latest deploy log https://app.netlify.com/projects/wolfstar-rocks-et34281/deploys/69e63a34fa2f4c000898f92b
😎 Deploy Preview https://deploy-preview-144.wolfstar.rocks
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 82 (no change from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 94 (no change from production)
PWA: 90 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI changed the title [WIP] Add logging system for modifications and notifications feat(audit-log): dashboard audit log system with slideover UI Apr 11, 2026
Copilot AI requested a review from RedStar071 April 11, 2026 20:08
@sentry
Copy link
Copy Markdown

sentry Bot commented Apr 11, 2026

❌ 7 Tests Failed:

Tests completed Failed Passed Skipped
1102 7 1095 1
View the top 3 failed test(s) by shortest run time
test/unit/app/utils/audit-log.test.ts > auditLogChangeLines > messagesModerationDm changed false -> true gives Disabled/Enabled
Stack Traces | 0.000311s run time
TypeError: auditLogChangeLines is not a function
 ❯ .../app/utils/audit-log.test.ts:106:17
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:302:14
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:1903:28
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2326:24
 ❯ runWithCancel node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2323:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2305:24
 ❯ runWithTimeout node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2272:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2955:70
test/unit/app/utils/audit-log.test.ts > auditLogChangeLines > channelsIgnoreReactionAdd changed to many channels triggers truncation
Stack Traces | 0.000376s run time
TypeError: auditLogChangeLines is not a function
 ❯ .../app/utils/audit-log.test.ts:91:17
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:302:14
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:1903:28
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2326:24
 ❯ runWithCancel node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2323:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2305:24
 ❯ runWithTimeout node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2272:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2955:70
test/unit/app/utils/audit-log.test.ts > auditLogChangeLines > rolesAdmin changed includes resolved name and unknown-role fallback
Stack Traces | 0.000481s run time
TypeError: auditLogChangeLines is not a function
 ❯ .../app/utils/audit-log.test.ts:75:17
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:302:14
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:1903:28
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2326:24
 ❯ runWithCancel node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2323:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2305:24
 ❯ runWithTimeout node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2272:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2955:70
test/unit/app/utils/audit-log.test.ts > auditLogChangeLines > rolesAdmin added with two roles resolves names
Stack Traces | 0.00055s run time
TypeError: auditLogChangeLines is not a function
 ❯ .../app/utils/audit-log.test.ts:59:17
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:302:14
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:1903:28
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2326:24
 ❯ runWithCancel node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2323:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2305:24
 ❯ runWithTimeout node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2272:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2955:70
test/unit/app/utils/audit-log.test.ts > auditLogChangeLines > unknown key foo.bar.bazQux removed -> label is humanized
Stack Traces | 0.0013s run time
TypeError: auditLogChangeLines is not a function
 ❯ .../app/utils/audit-log.test.ts:113:17
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:302:14
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:1903:28
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2326:24
 ❯ runWithCancel node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2323:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2305:24
 ❯ runWithTimeout node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2272:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2955:70
test/unit/app/utils/audit-log.test.ts > auditLogChangeLines > returns empty array for empty changes
Stack Traces | 0.0055s run time
TypeError: auditLogChangeLines is not a function
 ❯ .../app/utils/audit-log.test.ts:54:10
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:302:14
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:1903:28
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2326:24
 ❯ runWithCancel node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2323:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2305:24
 ❯ runWithTimeout node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2272:12
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:2955:70
test/unit/audit/postgres-drain.spec.ts > createPostgresAuditDrain > stores and hashes the top-level audit.tenantId field correctly
Stack Traces | 0.00711s run time
AssertionError: expected undefined to be 'tenant-123' // Object.is equality

- Expected:
"tenant-123"

+ Received:
undefined

 ❯ .../unit/audit/postgres-drain.spec.ts:147:25
 ❯ node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.19_@opentelemetry+api@1.9.1_@types+node@24.12.2_@vites_660afa3a5f4205f97234bc18b872af90/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js:1903:22

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 11, 2026

Merging this PR will not alter performance

✅ 44 untouched benchmarks


Comparing copilot/create-log-system-for-changes (8b4dffd) with main (b8f2720)

Open in CodSpeed

@github-actions
Copy link
Copy Markdown
Contributor

Contribution Guidelines Review

Thanks for this detailed PR — the audit log feature is well-described and the title follows Conventional Commits format correctly. ✅

There's one item from the contribution guidelines that needs attention before this can be marked ready:

📸 Missing screenshots for frontend changes

The guidelines state:

Where frontend changes are made, please include before and after screenshots in your pull request description.

This PR introduces AuditLogSlideover.vue and integrates a bell icon + N shortcut into the manage.vue navbar — both are visible frontend changes. Please add before/after screenshots (or a short screen recording) to the PR description showing:

  • The navbar before and after the bell icon was added
  • The audit log slideover UI (open/loading/empty states)

✅ Everything else looks good

Check Status
PR title format (type(scope): description)
Lowercase title
Detailed PR description with clear sections
Draft state (appropriate while in progress)

Once screenshots are added and the PR is marked ready for review, this should be good to go!

Generated by Contribution Guidelines Checker for issue #144 · ● 233.2K ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/contribution-guidelines-checker.md@1f672aef974f4246124860fc532f82fe8a93a57e

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — Audit Log System (draft)

This is a solid feature addition with a clean architecture. CI shows lint ✅ · unit tests ✅ · component tests ✅ — but 🧹 Unused code check ❌ is failing (needs investigation before merge). Browser tests, accessibility audits and benchmarks were still running at review time.

Since this is a draft I'm not blocking merge, but there are two runtime-breaking bugs that must be addressed before this is ready.


🐛 Must fix (runtime errors)

# File Issue
1 server/database/schema.prisma Model named AuditLog generates prisma.auditLog, but all code calls prisma.dashboardAuditLog. Also @@Map("audit_log") disagrees with the migration's dashboard_audit_log table. Fix: rename model to DashboardAuditLog and change @@map`` to "dashboard_audit_log".
2 shared/schemas/audit-log.ts number() rejects string query params — every request to GET /audit-logs?limit=50 will return 400. Use coerce(number(), Number) (see inline comment).

⚠️ Should address

# File Issue
3 server/api/guilds/[guild]/settings.patch.ts deriveSection classifies the whole batch by keys[0] only — mixed-section saves are mislabelled.
4 app/composables/useAuditLog.ts Cache key is a static string evaluated once at setup — pass a getter () => \guild:...`` so Nuxt can react to guild navigation.
5 app/components/guild/AuditLogSlideover.vue Entries list lacks aria-live="polite" — screen reader users won't know when content refreshes.

💡 Nice-to-have

# File Suggestion
6 AuditLogSlideover.vue Replace hand-rolled formatRelativeTime with useTimeAgo from VueUse — it's already in the project and stays reactive as time passes.

🧹 CI failure

The unused code check is failing — likely caused by the new AuditLogQuery type export or another export not yet consumed. Run pnpm knip locally and add any genuinely unused exports to the knip ignore list, or wire them up properly.

Generated by WolfStar Code Quality Reviewer for issue #144 · ● 778.1K

Comment thread shared/schemas/audit-log.ts Outdated
Comment thread server/database/schema.prisma Outdated
Comment thread server/api/guilds/[guild]/settings.patch.ts Outdated
Comment thread app/composables/useAuditLog.ts Outdated
Comment thread app/components/AuditLogSlideover.vue Outdated
Comment thread app/components/AuditLogSlideover.vue Outdated
@github-actions
Copy link
Copy Markdown
Contributor

Contribution Guidelines Review 🔍

Hi @RedStar071! Thanks for working on this — an audit log system is a great addition to the dashboard. Here's a quick review against the contribution guidelines.

✅ What looks good

  • PR title follows Conventional Commits format (feat(audit-log): ...), uses lowercase ✓
  • Description is well-structured with clear sections (Database, Server, Shared, Frontend) ✓
  • Commit messages don't need to follow the format since they'll be squashed on merge ✓

🔧 A couple of things to address

1. Missing before/after screenshots

The guidelines require:

Where frontend changes are made, please include before and after screenshots in your pull request description.

This PR adds a new AuditLogSlideover.vue component and integrates it into manage.vue — please add screenshots of the UI before and after your changes to the PR description.

2. PR is still in draft

The PR is currently marked as a draft, which typically means it isn't ready for review or merge yet. When the implementation is complete and the checklist below is done, mark it as "Ready for review".


📋 Pre-submission checklist

Before marking ready for review, please confirm:

  • pnpm lint:fix passes
  • pnpm typecheck passes
  • pnpm test passes
  • pnpm build succeeds
  • Before/after screenshots added to the PR description

Once those are addressed, this will be in great shape! Feel free to ping when it's ready. 🚀

Generated by Contribution Guidelines Checker for issue #144 · ● 227K ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/contribution-guidelines-checker.md@1f672aef974f4246124860fc532f82fe8a93a57e

@github-actions
Copy link
Copy Markdown
Contributor

Contribution Guidelines Review 👋

Thanks for this detailed PR! The implementation looks well-structured and the description clearly explains the changes across the database, server, shared, and frontend layers. A few contribution process items to address before this is ready for review:

❌ Missing screenshots for frontend changes

The contribution guidelines require:

"Where frontend changes are made, please include before and after screenshots in your pull request description."

This PR introduces a new AuditLogSlideover.vue component and integrates it into the manage.vue navbar, but the description doesn't include any screenshots. Please add before/after screenshots showing:

  • The new bell icon in the navbar
  • The slideover panel open with audit log entries
  • Loading/empty states (if possible)

i️ PR is still in draft

The PR is currently marked as a draft. Once the implementation is complete and CI checks pass (build, lint, typecheck, tests), please mark it as ready for review.

✅ What looks good

  • PR title: feat(audit-log): dashboard audit log system with slideover UI — correct Conventional Commits format, lowercase ✓
  • Description: Well-structured with clear sections explaining the changes ✓
  • Scope: audit-log is descriptive and appropriate ✓

Once screenshots are added and the draft status is removed, this will be much closer to ready. Let us know if you have any questions!

Generated by Contribution Guidelines Checker for issue #144 · ● 233.1K ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/contribution-guidelines-checker.md@1f672aef974f4246124860fc532f82fe8a93a57e

github-actions[bot]

This comment was marked as outdated.

@RedStar071
Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

@github-actions
Copy link
Copy Markdown
Contributor

Contribution Guidelines Review ✅

This PR has been reviewed against the contribution guidelines and meets all requirements:

Check Status
PR title follows type(scope): description (Conventional Commits)
Title uses lowercase
Description explains what and why
Screenshots included for frontend changes
Database migration included with descriptive naming
Structured sections covering all changed areas

The contribution-ready label has been added.

Note: This PR is currently in draft state. When you're happy with the implementation and all CI checks pass, remember to mark it as ready for review so maintainers can take a look!

Generated by Contribution Guidelines Checker for issue #144 · ● 373.3K ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/contribution-guidelines-checker.md@1f672aef974f4246124860fc532f82fe8a93a57e

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a dashboard-facing audit log system for guild settings changes, including persistence in the database, server endpoints to query activity, and UI surfaces (recent activity panel + slideover) to view entries.

Changes:

  • Added Prisma AuditLog model + migrations, and server-side AuditLogManager for recording/fetching entries.
  • Updated guild settings PATCH flow to write audit entries on settings updates, and added GET /api/guilds/:guild/audit-logs (plus moderation list endpoint and supporting schemas/composables).
  • Added frontend UI for recent activity and an “Activity Log” slideover, wired into the guild manage navbar.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
shared/utils/moderationConstants.ts Adds moderation labels/icons/severity helpers for new “Recent Activity” UI.
shared/types/prisma.ts Extends PrismaJson typings to include audit log change arrays.
shared/schemas/moderation.ts Adds query schema for moderation list endpoint.
shared/schemas/index.ts Re-exports new schemas.
shared/schemas/audit-log.ts Adds query schema for audit log endpoint pagination.
server/database/settings/types.ts Introduces audit-log-related types for settings/database layer.
server/database/settings/structures/AuditLogManager.ts Implements audit log write + fetch logic, including member hydration.
server/database/settings/functions.ts Exposes readSettingsAuditLog() from settings context.
server/database/settings/context/SettingsContext.ts Wires AuditLogManager into per-guild settings context lifecycle.
server/database/schema.prisma Adds AuditLog model and relation to Guild.
server/database/migrations/20260412130548_audit_log_remove_username_add_guild_fk/migration.sql Drops prior table and creates audit_log with FK + index.
server/database/migrations/20260411190000_add_dashboard_audit_log/migration.sql Initial migration adding dashboard_audit_log (later superseded by next migration).
server/api/guilds/[guild]/settings.patch.ts Adds fire-and-forget audit log write when settings are patched.
server/api/guilds/[guild]/moderation.get.ts Adds moderation cases list endpoint.
server/api/guilds/[guild]/audit-logs.get.ts Adds audit log list endpoint.
app/pages/(app)/guilds/[...id]/manage.vue Integrates Activity Log trigger + slideover into the dashboard navbar.
app/composables/useModerationCases.ts Adds composable to fetch moderation cases + total.
app/composables/useAuditLog.ts Adds composable to fetch audit log entries + total.
app/components/guild/settings/General.vue Adds “Recent Activity” panel showing audit changes and moderation cases.
app/components/guild/card.vue Small template formatting/layout tweak.
app/components/AuditLogSlideover.vue Adds Activity Log slideover UI.

Comment thread server/api/guilds/[guild]/audit-logs.get.ts Outdated
Comment thread server/api/guilds/[guild]/moderation.get.ts Outdated
Comment thread server/api/guilds/[guild]/settings.patch.ts Outdated
Comment thread server/database/settings/structures/AuditLogManager.ts Outdated
Comment thread server/database/schema.prisma Outdated
Comment thread server/database/migrations/20260411190000_add_dashboard_audit_log/migration.sql Outdated
Comment thread server/database/settings/types.ts Outdated
Comment thread app/components/AuditLogSlideover.vue Outdated
Comment thread server/api/guilds/[guild]/settings.patch.ts Outdated
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — feat(audit-log): dashboard audit log system

Draft PR — no merge decision, but flagging issues that need attention before this is ready.

CI status

Check Result
🔠 Lint ✅ Passed
🧪 Unit tests ✅ Passed
🧪 Component tests ✅ Passed
🧹 Unused code (knip) Failed
🖥️ Browser tests 🔄 In progress
♿ Accessibility audits 🔄 In progress
⚡ Benchmarks 🔄 In progress

Must fix before merge

  • ❌ Unused code check failing (shared/utils/moderationConstants.ts + shared/schemas/moderation.ts) — 9 exported symbols are never consumed. Remove export from internal helpers and types that aren't used outside the file, and drop ModerationQuery from the schema if it isn't referenced elsewhere. See inline comment on moderationConstants.ts.

  • 🐛 Audit log diff always shows oldValue === newValueAuditLogManager.update() is called after the settings write, but SettingsContext.update()onPatch() runs during the write and overwrites this.#settings with the new state first. The fix is to snapshot old values synchronously before the trx.write().submit() call. See inline comment on settings.patch.ts:69.

  • 🔴 TypeScript error: AuditLogChanges not in scopeAuditLogChanges is a PrismaJson namespace type and cannot be used as a bare identifier in AuditLogManager.ts. Replace with the already-imported AuditLogChange[]. See inline comment on AuditLogManager.ts:56.


Suggestions

  • MaybeRefOrGetter not reactive in useAuditLog / useModerationCasestoValue(guildId) resolves once at init; if the ref ever changes the composable won't re-fetch. Narrow the type to string to match actual usage.
  • sectionIcons map is duplicated — defined identically in AuditLogSlideover.vue and General.vue; consider a shared constant.
  • Prisma changes default@default("{}") creates a JSON object, but the type is AuditLogChange[] (an array). Use @default("[]") and update both migration SQL files accordingly.
  • member.user optional access in getMemberDisplayAPIGuildMember.user is typed as optional; add a null guard.

The overall design is solid — layered well from schema → server → composable → UI, the deriveSection logic is clear, and the slideover pattern matches existing conventions. The audit diff timing bug is the most important correctness issue to get right before promoting this out of draft.

Generated by WolfStar Code Quality Reviewer for issue #144 · ● 1.5M

Comment thread server/api/guilds/[guild]/settings.patch.ts Outdated
Comment thread server/database/settings/structures/AuditLogManager.ts Outdated
Comment thread shared/utils/moderationConstants.ts Outdated
Comment thread server/database/schema.prisma Outdated
Comment thread app/components/AuditLogSlideover.vue Outdated
Comment thread app/components/AuditLogSlideover.vue Outdated
Comment thread app/composables/useAuditLog.ts Outdated
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 12, 2026

@copilot apply changes based on the comments in this thread

All review feedback addressed in ad7bcd0:

  • Runtime bugs fixed: valibot schema coercion for query params (unknown() → transform(Number)), Prisma JSON default '{}' → '[]', optional member.user guard
  • Reactivity fixed: useAuditLog now uses function-based cache key with toValue()
  • A11y improved: aria-live="polite" on loading/content regions, distinct lucide:loader-2 spinner vs refresh icon, member name now rendered alongside avatar
  • Type fixed: AuditLogChangesAuditLogChange[], explicit getMember import
  • Section derivation improved: majority-vote across all keys instead of first-key-only
  • 🚨 BLOCKING Knip fixed: removed all unused moderation-cases scaffolding (4 files deleted, references cleaned from General.vue and schema index)

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.fontshare.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build git 0/node_modules/tinypool/dist/entry/process.js copilot/create-log-system-for-ch-- (dns block)
  • api.fontsource.org
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build git 0/node_modules/tinypool/dist/entry/process.js copilot/create-log-system-for-ch-- (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.14_@opentelemetry+api@1.9.1_@types+node@24.12.0_@vites_ff1e595bd8a2174e48dd0dd06e1f6fd9/node_modules/@voidzero-dev/vite-plus-test/dist/cli.js run --project unit HEAD (dns block)
  • api.iconify.design
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build git 0/node_modules/tinypool/dist/entry/process.js copilot/create-log-system-for-ch-- (dns block)
  • checkpoint.prisma.io
    • Triggering command: /opt/hostedtoolcache/node/24.14.1/x64/bin/node /opt/hostedtoolcache/node/24.14.1/x64/bin/node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.pnpm/prisma@7.7.0_@types+react@19.2.14_magicast@0.5.2_react-dom@19.2.5_react@19.2.5__react@19.2.5_typescript@5.9.3/node_modules/prisma/build/child {"product":"prisma","version":"7.7.0","cli_install_type":"local","information":"","local_timestamp":"2026-04-12T16:12:01Z","project_hash":"8cee999f","cli_path":"/home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/prisma/build/index.js","cli_path_ (dns block)
    • Triggering command: /opt/hostedtoolcache/node/24.14.1/x64/bin/node /opt/hostedtoolcache/node/24.14.1/x64/bin/node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.pnpm/prisma@7.7.0_@types+react@19.2.14_magicast@0.5.2_react-dom@19.2.5_react@19.2.5__react@19.2.5_typescript@5.9.3/node_modules/prisma/build/child {"product":"prisma","version":"7.7.0","cli_install_type":"local","information":"","local_timestamp":"2026-04-12T16:16:25Z","project_hash":"8cee999f","cli_path":"/home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/prisma/build/index.js","cli_path_ git rev-�� --abbrev-ref HEAD cal/bin/git (dns block)
  • fonts.bunny.net
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build git 0/node_modules/tinypool/dist/entry/process.js copilot/create-log-system-for-ch-- (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.14_@opentelemetry+api@1.9.1_@types+node@24.12.0_@vites_ff1e595bd8a2174e48dd0dd06e1f6fd9/node_modules/@voidzero-dev/vite-plus-test/dist/cli.js run --project unit HEAD (dns block)
  • fonts.google.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.bin/../nuxt/bin/nuxt.mjs build git 0/node_modules/tinypool/dist/entry/process.js copilot/create-log-system-for-ch-- (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/wolfstar.rocks/wolfstar.rocks/node_modules/.pnpm/@voidzero-dev+vite-plus-test@0.1.14_@opentelemetry+api@1.9.1_@types+node@24.12.0_@vites_ff1e595bd8a2174e48dd0dd06e1f6fd9/node_modules/@voidzero-dev/vite-plus-test/dist/cli.js run --project unit HEAD (dns block)
  • https://api.github.com/repos/wolfstar-project/wolfstar.rocks/pulls/144/comments
    • Triggering command: /usr/bin/curl curl -s REDACTED (http block)
  • https://api.github.com/repos/wolfstar-project/wolfstar.rocks/pulls/144/reviews
    • Triggering command: /usr/bin/curl curl -s REDACTED (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@github-actions
Copy link
Copy Markdown
Contributor

Hey @RedStar071 👋 Thanks for this contribution — the audit log system looks like a well-thought-out addition!

I ran a quick check against the contribution guidelines. Here's where things stand:

✅ Looks good

  • PR title follows Conventional Commits format (feat(audit-log): ..., lowercase) ✓
  • Description is thorough — covers Database, Server, Shared, and Frontend changes ✓
  • Screenshot included for the new UI ✓

⏳ Before marking ready

This PR is currently in draft state, so I'm holding off on the contribution-ready label for now. Before moving it to "Ready for review", please confirm the pre-submit checklist from the contributing guide:

  • pnpm lint:fix — linting passes
  • pnpm typecheck — no type errors
  • pnpm test — all tests pass
  • pnpm build — production build succeeds

Once those are green and you mark the PR as ready, feel free to ping for another look and the label can be added then. 🚀

Generated by Contribution Guidelines Checker for issue #144 · ● 368.2K ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/contribution-guidelines-checker.md@1f672aef974f4246124860fc532f82fe8a93a57e

github-actions[bot]

This comment was marked as outdated.

@github-actions
Copy link
Copy Markdown
Contributor

Thanks for this contribution! The implementation looks substantial and well thought-out. Before this PR can move forward, there are a few contribution process items to address. 👇

PR Template

The description doesn't follow the PR template. Please update it to include the required sections:

  • 🔗 Linked issue — Is there an open issue this addresses? If so, include Fixes #<number> or Closes #<number>. If not, consider opening one first so the feature can be discussed before the implementation is merged.
  • 🧭 Context — A brief explanation of why this change is needed and the background behind it.
  • 📚 Description — A description of what changed in your own words.

The technical detail in the current description is great — it just needs to be restructured into the template format.

Own words, please

From CONTRIBUTING.md § Using AI:

Never let an LLM speak for you. When you write a comment, issue, or PR description, use your own words. AI-generated summaries tend to be long-winded, dense, and often inaccurate. The goal is not to sound impressive, but to communicate clearly.

The current description reads as AI-generated. Please rewrite it in your own voice — even a few plain sentences explaining what this does and why you built it is far more valuable than a detailed AI summary.

Draft status

This PR is currently marked as a draft. When it's ready for review, please mark it as ready and ensure CI checks pass (lint, typecheck, build, tests).


Once those are addressed, re-request review and a maintainer will take a look. Thanks again for contributing! 🙌

Generated by Contribution Guidelines Checker for issue #144 · ● 291.1K ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/contribution-guidelines-checker.md@1f672aef974f4246124860fc532f82fe8a93a57e

github-actions[bot]

This comment was marked as outdated.

* Introduced new columns in the Guild model for:
  - Command execution logs
  - Settings change logs
* Updated migration file to reflect these changes.
* Add status label to log filters
* Improve empty state messages for log tables
* Format timestamps using `formatTimeAgo` for better readability
- Update UTable to show loading state for both 'pending' and 'idle'.
- Add action type filter to ModerationLogTable for better log management.
- Refactor audit logging to simplify change tracking.
- Update async data retrieval for audit, command, and moderation logs
- Include resolved limit and offset in the data key for better pagination
- Simplify cache invalidation logic for manual and hook refreshes
* Refactor log response handlers to use cached response handling.
* Add maxAge and swr options for improved caching.
* Implement getKey function for unique cache keys based on guild and request URL.
* Updated search input to use debounced query for better performance.
* Improved pagination handling with dynamic total entries display.
* Refactored user display in the activity log for better UI consistency.
* Integrate auditDiff to capture changes in settings.
* Improve clarity of audit logs by including before and after states.
* Refactored patchToChanges to utilize getNestedValue for accessing nested properties.
* Enhanced diff processing to limit the number of operations processed.
* Updated changes structure to directly pass before and after settings for audit logging.
@RedStar071
Copy link
Copy Markdown
Member

@copilot fix ci failed

…access, fix any type"

Agent-Logs-Url: https://github.com/wolfstar-project/wolfstar.rocks/sessions/2e965151-4a59-4dfa-80e9-7d5578c07275

Co-authored-by: RedStar071 <76824516+RedStar071@users.noreply.github.com>
Copilot stopped work on behalf of RedStar071 due to an error May 18, 2026 17:24
RedStar071 added 11 commits May 19, 2026 17:09
* Updated swr option to false in commands, index, and moderation log handlers.
* This change improves response caching behavior.
* Introduced new utility functions for handling audit changes.
* Added metadata management for audit fields.
* Created tests for audit log functionalities.
* Removed deprecated schemas and functions to streamline codebase.
* Enhanced logging descriptions for better clarity and usability.
* Include @tanstack/table-core in the ignoreDependencies list
* Ensures proper handling of dependencies in guild/logs components
- Updated function name for clarity and consistency.
- Removed alias for resolveGuildMembers to streamline code.
- Move mock entries for command, audit, and moderation logs.
* Replace CommandLogEntry with CommandLogData for better clarity.
* Introduce commandType and commandId fields in CommandLog model.
* Remove deprecated command log type definitions.
* Add commandType and commandId to command log entries
* Move metadata field to the end of the entry structure
* Change CommandLogEntry to CommandLogData for consistency
* Update mock command entry to reflect new data structure
* Adjust variable names for clarity in log table component
- Changed type from CommandLogEntry to CommandLogData
- Updated fetch calls in tests to reflect new type
@RedStar071
Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request

…stem-for-changes

# Conflicts:
#	.github/workflows/semantic-pull-requests.yml
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 27, 2026

@copilot resolve the merge conflicts in this pull request

Merge conflicts resolved in 09c8d901.

There was one conflict in .github/workflows/semantic-pull-requests.yml — both branches had added different scopes to the PR title validator. I merged both scope lists into a single sorted union:

HEAD (PR branch) added: audit-log, blog, cli, evlog, i18n
origin/main added: api, auth, ci, config, dashboard, database, guild, oauth, pwa, sentry, seo, test

The merged result includes all scopes from both branches. All other changes from origin/main (20 commits: CI hardening, knip v6 upgrade, workflow renames, new test-secrets module, pnpm-lock updates, etc.) merged cleanly without conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants