feat(door): P2 connections + SSRF-safe executor + native adapter + audit
Migration 035 adds door_connections (per-space controller integration: secret_ref -> AES-256-GCM secrets vault, never a plaintext password; pinned_host SSRF pin; native_heatsync|generic_http adapter; allow_member_self_entry opt-in for phase 3) and door_access_log (append-only, secrets redacted, service-client-only writes; immutable). RLS additive/default-deny: connections CRUD = door.manage; log SELECT = door.manage/operate. Safety core is pure and heavily unit-tested (door-logic, suite 409): validateDoorTarget (request host must equal the pinned host; metadata/link-local always blocked; http(s) only), the firmware-verified HeatSync encoders with fixed-width zero-padding (slot 3 / perm 3 / tag 8 / 4-char password), generic template substitution, and redactDoorSecrets. lib/door/executor.ts is the single hardened egress: re-validates the pin, refuses redirects, caps time and body, redacts before any audit write. The door password is read from the secrets vault and decrypted server-side only, never returned or logged. /door/manage (door.manage) configures connections, picks a vault secret, and runs a safe status-only test. Sidebar Admin link added; "Learn" moved before "People" per request. Docs updated.
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
||||
MessageSquare, Users, CreditCard, BookUser, Download, LogOut,
|
||||
Vote, ShieldAlert, ScrollText, LineChart, UserCircle, UserSearch,
|
||||
MessagesSquare, SlidersHorizontal, ClipboardList, FileText, Award, BadgeCheck, GraduationCap, Hammer,
|
||||
ChevronDown,
|
||||
ChevronDown, DoorClosed,
|
||||
} from 'lucide-react'
|
||||
|
||||
interface NavLinkProps {
|
||||
@@ -173,6 +173,12 @@ export function AppSidebar({ member, roleName, taskBadge = 0, commsBadge = 0, pa
|
||||
<NavLink href="/policies" label="Policies" icon={ScrollText} active={isActive('/policies')} onClick={onNav} />
|
||||
</NavSection>
|
||||
|
||||
<NavSection id="learn" title="Learn">
|
||||
<NavLink href="/classes" label="Classes" icon={GraduationCap} active={pathname === '/classes' || pathname.startsWith('/classes?')} onClick={onNav} />
|
||||
<NavLink href="/equipment" label="Equipment" icon={Hammer} active={pathname === '/equipment' || pathname.startsWith('/equipment?')} onClick={onNav} />
|
||||
<NavLink href="/my-forms" label="Forms" icon={FileText} active={isActive('/my-forms')} onClick={onNav} />
|
||||
</NavSection>
|
||||
|
||||
<NavSection id="people" title="People">
|
||||
<NavLink href="/members" label="Members" icon={Users} active={isActive('/members')} onClick={onNav} />
|
||||
<NavLink href="/contacts" label="Contacts" icon={BookUser} active={isActive('/contacts')} onClick={onNav} />
|
||||
@@ -186,12 +192,6 @@ export function AppSidebar({ member, roleName, taskBadge = 0, commsBadge = 0, pa
|
||||
<NavLink href="/financials" label="Financials" icon={LineChart} active={isActive('/financials')} onClick={onNav} />
|
||||
</NavSection>
|
||||
|
||||
<NavSection id="learn" title="Learn">
|
||||
<NavLink href="/classes" label="Classes" icon={GraduationCap} active={pathname === '/classes' || pathname.startsWith('/classes?')} onClick={onNav} />
|
||||
<NavLink href="/equipment" label="Equipment" icon={Hammer} active={pathname === '/equipment' || pathname.startsWith('/equipment?')} onClick={onNav} />
|
||||
<NavLink href="/my-forms" label="Forms" icon={FileText} active={isActive('/my-forms')} onClick={onNav} />
|
||||
</NavSection>
|
||||
|
||||
<NavSection id="account" title="Account">
|
||||
<NavLink href="/profile" label="My profile" icon={UserCircle} active={isActive('/profile')} onClick={onNav} />
|
||||
<NavLink href="/me" label="My access" icon={BadgeCheck} active={isActive('/me')} onClick={onNav} />
|
||||
@@ -204,6 +204,7 @@ export function AppSidebar({ member, roleName, taskBadge = 0, commsBadge = 0, pa
|
||||
<NavLink href="/certifications" label="Certifications" icon={Award} active={isActive('/certifications')} onClick={onNav} />
|
||||
<NavLink href="/classes/manage" label="Manage classes" icon={GraduationCap} active={isActive('/classes/manage')} onClick={onNav} />
|
||||
<NavLink href="/equipment/manage" label="Manage equipment" icon={Hammer} active={isActive('/equipment/manage')} onClick={onNav} />
|
||||
<NavLink href="/door/manage" label="Door access" icon={DoorClosed} active={isActive('/door/manage')} onClick={onNav} />
|
||||
<NavLink href="/import" label="Import / Sync" icon={Download} active={isActive('/import')} onClick={onNav} />
|
||||
<NavLink href="/settings" label="Settings" icon={Settings2} active={isActive('/settings')} onClick={onNav} />
|
||||
</NavSection>
|
||||
|
||||
Reference in New Issue
Block a user