feat(m4): frontend MitreTagPicker + /mitre showcase page

- lib/mitre.ts: shared types (MitreTactic, Technique, Subtechnique, MitreTag
  kind/id/external_id/name) + TanStack query keys.
- components/MitreTagPicker.tsx: three-column controlled picker (tactic →
  technique → subtechnique), multi-select with chip-removal, autocomplete on
  each column, ARIA labels for screen readers. Returns MitreTag[] via
  value/onChange — drop-in for M5 template forms.
- pages/MitrePage.tsx: status card (version, source URL, last_sync), admin-
  gated Trigger Sync button with success/error alerts, picker showcase, JSON
  preview of the current selection.
- Layout adds MITRE nav link for any logged-in user; App.tsx adds the
  /mitre route under RequireAuth. HomePage roadmap bumped to next: M5
  templates.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Knacky
2026-05-12 13:54:15 +02:00
parent 872f3c046a
commit 8a1dd58c83
6 changed files with 465 additions and 4 deletions

View File

@@ -36,6 +36,7 @@ export function Layout() {
<>
{navItem('/', 'Home')}
{navItem('/profile', 'Profile')}
{navItem('/mitre', 'MITRE')}
{state.user.is_admin && (
<>
{navItem('/admin/users', 'Users')}
@@ -68,7 +69,7 @@ export function Layout() {
<Outlet />
<footer className="mt-[60px] py-8 border-t border-border text-center font-mono text-xs text-text-dim">
metamorph · M0 bootstrap · M1 db schema · M2 auth · M3 rbac · design system from tasks/design.md
metamorph · M0 bootstrap · M1 db schema · M2 auth · M3 rbac · M4 mitre · design system from tasks/design.md
</footer>
</div>
</div>