diff --git a/apps/web/package.json b/apps/web/package.json index bfe00e20..70b8b518 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -17,27 +17,27 @@ "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@tailwindcss/postcss": "^4.3.3", - "@tiptap/core": "^3.30.4", - "@tiptap/extension-code-block-lowlight": "^3.30.4", - "@tiptap/extension-details": "^3.30.4", - "@tiptap/extension-document": "^3.30.4", - "@tiptap/extension-highlight": "^3.30.4", - "@tiptap/extension-image": "^3.30.4", - "@tiptap/extension-link": "^3.30.4", - "@tiptap/extension-paragraph": "^3.30.4", - "@tiptap/extension-placeholder": "^3.30.4", - "@tiptap/extension-table": "^3.30.4", - "@tiptap/extension-table-cell": "^3.30.4", - "@tiptap/extension-table-header": "^3.30.4", - "@tiptap/extension-table-row": "^3.30.4", - "@tiptap/extension-task-item": "^3.30.4", - "@tiptap/extension-task-list": "^3.30.4", - "@tiptap/extension-text": "^3.30.4", - "@tiptap/extension-underline": "^3.30.4", - "@tiptap/pm": "^3.30.4", - "@tiptap/react": "^3.30.4", - "@tiptap/starter-kit": "^3.30.4", - "@tiptap/suggestion": "^3.30.4", + "@tiptap/core": "^3.30.5", + "@tiptap/extension-code-block-lowlight": "^3.30.5", + "@tiptap/extension-details": "^3.30.5", + "@tiptap/extension-document": "^3.30.5", + "@tiptap/extension-highlight": "^3.30.5", + "@tiptap/extension-image": "^3.30.5", + "@tiptap/extension-link": "^3.30.5", + "@tiptap/extension-paragraph": "^3.30.5", + "@tiptap/extension-placeholder": "^3.30.5", + "@tiptap/extension-table": "^3.30.5", + "@tiptap/extension-table-cell": "^3.30.5", + "@tiptap/extension-table-header": "^3.30.5", + "@tiptap/extension-table-row": "^3.30.5", + "@tiptap/extension-task-item": "^3.30.5", + "@tiptap/extension-task-list": "^3.30.5", + "@tiptap/extension-text": "^3.30.5", + "@tiptap/extension-underline": "^3.30.5", + "@tiptap/pm": "^3.30.5", + "@tiptap/react": "^3.30.5", + "@tiptap/starter-kit": "^3.30.5", + "@tiptap/suggestion": "^3.30.5", "@types/react-resizable": "^4.0.0", "@types/turndown": "^5.0.6", "d3-drag": "^3.0.0", @@ -47,7 +47,7 @@ "dompurify": "^3.4.13", "lowlight": "^3.3.0", "lucide-react": "^1.31.0", - "next": "16.3.1", + "next": "16.3.3", "postcss": "^8.5.26", "react": "^19.2.8", "react-dom": "^19.2.8", @@ -75,7 +75,7 @@ "@types/react-grid-layout": "^1.3.6", "@types/simple-peer": "^9.11.9", "eslint": "^9.39.5", - "eslint-config-next": "16.3.1", + "eslint-config-next": "16.3.3", "typescript": "^6.0.3" } } diff --git a/apps/web/src/app/(app)/settings/ai/page.tsx b/apps/web/src/app/(app)/settings/ai/page.tsx index 1060b35e..bdd09d3d 100644 --- a/apps/web/src/app/(app)/settings/ai/page.tsx +++ b/apps/web/src/app/(app)/settings/ai/page.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'; import { api } from '@/lib/api'; import { useAuth } from '@/lib/auth-context'; +import { SettingsSectionNav } from '@/components/settings-section-nav'; import { Database, Eye, EyeOff, KeyRound, Loader2, Mic, RotateCcw, Save, Server, Sparkles, Trash2 } from 'lucide-react'; type Provider = 'anthropic' | 'openai' | 'openrouter' | 'ollama'; @@ -53,6 +54,7 @@ export default function AISettingsPage() { const [cfg, setCfg] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); + const [section, setSection] = useState<'providers' | 'models' | 'search' | 'voice'>('providers'); const isAdmin = user?.role === 'owner' || user?.role === 'admin'; @@ -83,10 +85,10 @@ export default function AISettingsPage() { className="text-[18px] font-semibold mb-3" style={{ color: 'var(--foreground)', fontFamily: 'var(--font-heading)' }} > - AI providers + AI configuration
Only owners and admins can configure AI providers for this workspace. @@ -107,28 +109,28 @@ export default function AISettingsPage() { if (!cfg) { return (
-
{error || 'Failed to load.'}
+
{error || 'Failed to load.'}
); } return (
-
-
-

+
+

- AI providers for {org?.name ?? 'your workspace'} -

-

+ AI configuration for {org?.name ?? 'your workspace'} +

+

Bring your own provider. Deft can use managed keys or local Ollama, and the core workspace keeps working when no AI provider is configured. Keys are encrypted at rest and only used for this workspace.

{!cfg.has_provider && (
AI is currently off. Chat, tasks, wiki, calendar, and approvals still work; Defty and AI-assisted @@ -137,27 +139,15 @@ export default function AISettingsPage() { )}
-
- - - -
- -
+ +
-
+ -
+ -
+
-

{label}

+

{label}

{configured ? ( )}
-

+

{hint}

{configured && display && ( @@ -342,7 +332,7 @@ function ProviderCard({ {!editing && (
-

{label}

-

+

{label}

+

{description}

@@ -523,7 +492,7 @@ function ModelRouteCard({

-

Transcription provider

+

Transcription provider

currently: {cfg.transcription.effective}
-

+

Pick the engine used for voice clips in chat. The org override wins; clear it to fall back to the env default.

@@ -852,7 +821,7 @@ function TranscriptionSection({ cfg, onSaved }: { cfg: AIConfig; onSaved: () =>
{err && ( -
+
{err}
)} @@ -879,7 +848,7 @@ function TranscriptionSection({ cfg, onSaved }: { cfg: AIConfig; onSaved: () => style={{ accentColor: 'var(--accent)' }} />
-

{opt.label}

+

{opt.label}

{opt.helper}

@@ -892,7 +861,7 @@ function TranscriptionSection({ cfg, onSaved }: { cfg: AIConfig; onSaved: () => type="button" onClick={reset} disabled={saving} - className="text-[12px] inline-flex items-center gap-1 disabled:opacity-50" + className="text-sm inline-flex items-center gap-1 disabled:opacity-50" style={{ color: 'var(--muted)' }} > @@ -901,8 +870,8 @@ function TranscriptionSection({ cfg, onSaved }: { cfg: AIConfig; onSaved: () => -
: undefined} /> +
+ : undefined} /> void inspect(event)} className="sr-only" aria-label="Choose a Deft App package" />
@@ -125,8 +132,24 @@ export function AppsClient() { {pending && setPending(null)} onStage={() => void stage()} />} {isLoading ?
: error ? } title="Apps did not load" description={error instanceof Error ? error.message : 'Try again.'} action={{ label: 'Try again', onClick: () => void mutate() }} /> - : apps.length === 0 ? } title="No Apps installed" description="Build a declarative App with the public kit, then inspect its package here." action={canManage ? { label: 'Inspect a package', onClick: () => choosePackage() } : undefined} /> - :
{apps.map((app) => void activate(app)} onDisable={() => void disable(app)} onChooseUpgrade={() => choosePackage(app)} />)}
} + : selectedId && !selectedApp ?

This App is unavailable in this workspace.

All Apps
+ : apps.length === 0 ? } title="No Apps installed" description="Inspect a Deft App package to review what it adds to your workspace." action={canManage ? { label: 'Inspect a package', onClick: () => choosePackage() } : undefined} /> + : selectedApp ? <> + ← All Apps + void activate(selectedApp)} onDisable={() => void disable(selectedApp)} onChooseUpgrade={() => choosePackage(selectedApp)} /> + :
+ + {visibleApps.length === 0 &&

No installed Apps match your search.

} + {visibleApps.map((app) => + + {app.name}v{app.version} · {app.manifest.modules.length} Module{app.manifest.modules.length === 1 ? '' : 's'} + {app.state} + + )} +
}
; diff --git a/apps/web/src/app/(app)/settings/calendar/page.tsx b/apps/web/src/app/(app)/settings/calendar/page.tsx index 6bd8c88f..476be0da 100644 --- a/apps/web/src/app/(app)/settings/calendar/page.tsx +++ b/apps/web/src/app/(app)/settings/calendar/page.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'; import { api } from '@/lib/api'; import { formatRelative } from '@/lib/time'; +import { SettingsSectionNav } from '@/components/settings-section-nav'; import { Calendar, Copy, @@ -84,23 +85,30 @@ function nextSyncAt(sub: Subscription): string { } export default function CalendarSettingsPage() { + const [section, setSection] = useState<'connected' | 'share'>('connected'); return (
-
-
-

+
+

- Calendar sync -

-

+ Calendar connections +

+

Connect calendars with ICS links: show Deft work in your calendar, and read external calendar events into Deft without OAuth.

- - + + +
); @@ -156,12 +164,12 @@ function OutboundSection() { return (

Show Deft in your calendar

-

+

Paste this URL into your calendar app to see your Deft tasks alongside your other events. Your calendar app re-fetches automatically — no OAuth, no plugin.

@@ -177,10 +185,10 @@ function OutboundSection() {
-

+

Your personal Deft feed URL

-

+

Tasks with due dates and synced events for the next 12 months.

@@ -189,7 +197,7 @@ function OutboundSection() {
{error && (
{error} @@ -197,7 +205,7 @@ function OutboundSection() { )} {loading ? ( -
+
Loading…
) : feedUrl ? ( @@ -207,13 +215,13 @@ function OutboundSection() { readOnly value={feedUrl} onFocus={(e) => e.currentTarget.select()} - className="flex-1 h-9 px-3 text-[12px] rounded-md outline-none font-mono" + className="flex-1 h-9 px-3 text-sm rounded-md outline-none font-mono" style={{ background: 'var(--surface)', border: '1px solid var(--border)', color: 'var(--foreground)' }} /> {howToOpen && ( -
+

Apple Calendar.{' '} File → New Calendar Subscription → paste the URL. @@ -260,7 +268,7 @@ function OutboundSection() { {confirmRegen ? (

@@ -271,7 +279,7 @@ function OutboundSection() { type="button" onClick={() => setConfirmRegen(false)} disabled={regenerating} - className="h-8 px-3 text-[12px] font-medium rounded-md" + className="h-8 px-3 text-sm font-medium rounded-md" style={{ background: 'var(--surface)', color: 'var(--foreground)', border: '1px solid var(--border)' }} > Cancel @@ -280,7 +288,7 @@ function OutboundSection() { type="button" onClick={regenerate} disabled={regenerating} - className="h-8 px-3 flex items-center gap-1.5 text-[12px] font-medium rounded-md disabled:opacity-50" + className="h-8 px-3 flex items-center gap-1.5 text-sm font-medium rounded-md disabled:opacity-50" style={{ background: 'var(--error)', color: 'white' }} > @@ -293,7 +301,7 @@ function OutboundSection() { type="button" onClick={() => setConfirmRegen(true)} disabled={!feedUrl} - className="inline-flex items-center gap-1.5 text-[12px] disabled:opacity-50" + className="inline-flex items-center gap-1.5 text-sm disabled:opacity-50" style={{ color: 'var(--muted)' }} > @@ -328,7 +336,7 @@ function InboundSection() {

Connect external calendars to Deft @@ -336,15 +344,15 @@ function InboundSection() { {!showAdd && ( )}

-

+

Paste a secret ICS feed URL from Google, iCloud, or Outlook to read those events into Deft. The agent uses them for context — nothing's sent back.

@@ -361,14 +369,14 @@ function InboundSection() {
{loading ? (
Loading subscriptions…
) : subs.length === 0 ? (
No inbound calendar subscriptions yet. Add one above to start ingesting events. @@ -388,7 +396,7 @@ function InboundSection() { {whereOpen && ( -
+

Google Calendar.{' '} Settings → Settings for my calendars → pick the calendar → Integrate calendar → "Secret address in iCal format". @@ -483,12 +491,12 @@ function AddSubscriptionForm({ style={{ background: 'var(--card-bg)', border: '1px solid var(--border)' }} > {err && ( -

+
{err}
)}
-
-
@@ -531,10 +539,10 @@ function AddSubscriptionForm({
-

+

{preview.calendar_name || 'Calendar feed'}

-

+

Found {preview.event_count} event{preview.event_count === 1 ? '' : 's'}.

@@ -545,7 +553,7 @@ function AddSubscriptionForm({ {preview.upcoming.length > 0 && (
{preview.upcoming.map((event) => ( -
+
{event.title} {formatDateTime(event.starts_at)}
@@ -556,7 +564,7 @@ function AddSubscriptionForm({ )}
-
- +
-
- -
- {CLIENT_OPTIONS.map((client) => { - const active = client.id === selectedClient; - return ( - + )} +
+ ) : ( +
+ {filteredConnections.map((connection) => ( +
+ + + {connection.kind === 'token' ? : } - {client.name} -
- {client.fit} -
-

{client.detail}

- - ); - })} -
-
-
- -
-
- {tokenSetupClient && ( -
-
-
- -
-
-

Choose what {selectedClientOption.name} can do

-

- Personal MCP tokens act as you. The app can only see what you can see, and every write is recorded under your name. -

- -
- {PRESETS.map((preset) => { - const active = preset.id === accessPreset; - return ( + + {connection.displayName} + + {connection.label} ·{' '} + {connection.last_used_at + ? `Last used ${formatDate(connection.last_used_at)}` + : 'Not used yet'} + + + + +
+
+

Access

+

+ {accessSummary(connection.scopes)} +

+ +
+
+

Recent activity

+ +
+

+ Added {formatDate(connection.created_at)} + {connection.kind === 'token' + ? ` · Token ${connection.token_prefix}…` + : ` · ${connection.connector_profile}`} +

+ {confirmRevoke === connection.key ? ( +
+ {error && ( +

+ {error} +

+ )} +

+ Revoke access for {connection.displayName}? It will stop accessing Deft. + To use it again, you will need to reconnect. +

+
+ + +
+
+ ) : ( - ); - })} -
- - {accessPreset === 'custom' && ( -
- {AVAILABLE_SCOPES.map((scope) => ( - - ))} + )}
- )} - -
- {selectedScopes.map((scope) => )} -
-
+ + ))}
-
- )} + )} + - {tokenSetupClient && ( -
-
-
- -
-
-

Create the connection

-

- Generate a token, copy the config for {selectedClientOption.name}, then test it from the AI app. +

+ + {historyOpen && ( +
+ {loadFailures.includes('Connection history') ? ( +

+ History could not be refreshed. Use Refresh to retry.

-
- setTokenName(e.target.value)} - className="h-10 rounded-md px-3 text-[13px] outline-none" - style={{ background: 'var(--surface-container)', color: 'var(--text-primary)', border: '1px solid var(--border-default)' }} - /> - -
- - {newToken && ( -
-
-
-
New token
-

Copy it now. Deft will not show it again.

-
- -
-
{newToken}
-
- )} - -
-
-
-
{selectedSnippet.title}
-

{selectedSnippet.detail}

-
- -
-
{selectedSnippet.value}
-
-
+ ) : loading && !history ? ( +

+ Loading history… +

+ ) : historyCount === 0 ? ( +

+ No revoked connections. +

+ ) : ( + [ + ...(history?.revoked_tokens.map((token) => ({ + ...token, + key: `token:${token.id}`, + displayName: token.name, + label: `Personal token ${token.token_prefix}…`, + })) ?? []), + ...(history?.revoked_grants.map((grant) => ({ + ...grant, + key: `grant:${grant.id}`, + displayName: grant.app_name, + label: grant.connector_profile, + })) ?? []), + ].map((connection) => ( +
+ + {connection.displayName} + + Revoked {formatDate(connection.revoked_at)} + + +

+ {connection.label} · Last used {formatDate(connection.last_used_at)} +

+ + +
+ )) + )}
-
+ )} + + + ) : ( +
+ + +

+ {setupStep === 0 + ? 'Which app would you like to connect?' + : setupStep === 1 + ? `Review access for ${selectedClientOption.name}` + : setupStep === 2 + ? `Connect ${selectedClientOption.name}` + : 'Check your connection'} +

+

+ {setupStep === 0 + ? 'Choose an app to see its setup instructions.' + : setupStep === 1 + ? 'Choose the access this app needs. Every action is recorded under your name.' + : setupStep === 2 + ? 'Complete the setup in your app, then come back to check its activity.' + : 'Run a request from your app and check whether Deft receives it.'} +

+ {error && ( +

+ {error} +

+ )} + {newToken && setupStep < 2 && ( +

+ A token has already been issued with these permissions. Return to Connect to save it. Start another + connection after finishing this setup to choose different access. +

)} - {selectedClientOption.setupKind === 'oauth' && ( -
-
-
- -
-
-
-
-

- {isClaudeConnector ? 'Claude connector setup' : 'ChatGPT custom app setup'} -

-

- {isClaudeConnector - ? 'Claude connectors are added from Claude settings at the account level. The URL/token cannot be pasted into an active chat and expected to work.' - : 'ChatGPT connects from OpenAI cloud, so Deft must be publicly reachable over HTTPS. The app uses Deft OAuth; do not paste a personal token into ChatGPT.'} -

-
- - {remote?.https_ready ? 'HTTPS ready' : 'Needs public HTTPS'} + {setupStep === 0 && ( +
+ {CLIENT_OPTIONS.map((client) => ( +
-
-
- -
-
- {isClaudeConnector ? 'Use Claude settings, not chat' : 'Use the app connector settings'} -
-
    - {remoteSteps.map((step) =>
  1. {step}
  2. )} -
-
-
-
-
- Security note: never paste a live bearer token into Claude, ChatGPT, or any AI chat. If you already did, revoke that personal token below and generate a fresh one. Remote Claude connectors should authenticate through Deft OAuth. -
- {isChatGptConnector && ( -
- ChatGPT availability: full read/write custom MCP apps currently require Business or Enterprise/Edu on ChatGPT web. Pro developer mode is limited to read/fetch access. Workspace admin or developer-mode controls may also apply. -
- )} - {isClaudeConnector && ( -
-
Fill Claude's four fields like this
-
- {claudeConnectorFields.map((field) => ( -
-
-
-
{field.label}
-
{field.value}
-
- {field.copyValue && ( - - )} -
-

{field.help}

-
- ))} -
-
+
+ {selectedClient === client.id && ( + )} -
- {remoteRows.slice(0, 3).map(([label, value]) => ( -
-
{label}
-
- {value ?? 'Not loaded'} - {value && ( - - )} -
-
- ))} -
- -
-
-
+ + ))} +
)} - {selectedClientOption.setupKind === 'agent' && ( -
-
-
- -
-
-

Use Agent Employees for shared workers

-

- Personal AI app connections act as you. If Hermes, OpenClaw, Codex, or another runtime should be available to the whole company as an employee, onboard it as an Agent Employee instead. + {setupStep === 1 && + (tokenSetupClient ? ( +

+ +
+

{selectedPreset.title}

+

+ {selectedPreset.detail} +

+

+ This does not give the app access to other people’s private work or bypass workspace permissions.

- - Open Agent Employees -
+ {accessPreset === 'custom' ? ( +
+ {AVAILABLE_SCOPES.map((scope) => ( + + ))} + {selectedScopes.length === 0 && ( +

+ Select at least one permission to continue. +

+ )} +
+ ) : ( + + )} +
+ ) : ( +
+

+ {selectedClientOption.setupKind === 'agent' + ? 'Shared employees have their own workspace access, policies and activity. Configure those in Agent employees.' + : 'Your app will open Deft’s authorization screen. Review the requested permissions there before allowing access.'} +

+

+ {selectedClientOption.setupKind === 'agent' + ? 'Your personal token will not be used to represent a shared employee.' + : 'You can inspect and revoke the resulting connection from Your connections.'} +

-
- )} -
+ ))} - -
- -
-
- -

Manage active connections

-
- {loading ? ( -
- ) : ( -
-
-
Personal tokens
- {tokens.length === 0 ? ( -

No personal MCP tokens yet.

) : ( -
- {tokens.map((token) => ( -
+ !remote.https_ready && ( +

+ Your Deft server needs a public HTTPS address before a hosted app can connect. Ask your workspace + administrator to configure it. +

+ ) + )} +
    + {remoteSteps.map((step) => ( +
  1. {step}
  2. + ))} +
+ {isClaudeConnector ? ( +
+ {claudeConnectorFields.map((field) => ( +
-
{token.name}
-
- {token.token_prefix}... / last used {formatDate(token.last_used_at)} -
+

{field.label}

+

+ {field.value} +

- -
-
- {isStale(token.last_used_at) && ( - - {token.last_used_at ? 'stale' : 'unused'} - + {field.copyValue && ( + )} - {token.scopes.map((scope) => ( - {scope} - ))} -
-
-
Recent token activity
-
+

+ {field.help} +

))}
- )} -
- -
-
OAuth app grants
- {grants.length === 0 ? ( -

No ChatGPT or Claude-style OAuth connections yet.

) : ( -
- {grants.map((grant) => ( -
-
-
-
{grant.app_name}
-
- {grant.connector_profile} / last used {formatDate(grant.last_used_at)} -
-
- -
-
- {isStale(grant.last_used_at) && ( - - {grant.last_used_at ? 'stale' : 'unused'} - - )} - {grant.scopes.map((scope) => ( - {scope} - ))} -
- -
- ))} +
+
+

Connector URL

+ {remote?.mcp_endpoint_url && ( + + )} +
+

+ {remote?.mcp_endpoint_url ?? 'Unavailable'} +

)} -
-
- )} -
- -
- + )} - {advancedOpen && ( -
- {remoteRows.map(([label, value]) => ( -
-
{label}
-
- {value ?? 'Not loaded'} - {value && ( - - )} -
+ {setupStep === 2 && selectedClientOption.setupKind === 'agent' && ( +

+ Continue in Agent employees to create or manage the shared worker, choose its access and configure its + runtime. +

+ )} + + {setupStep === 3 && ( +
+ {!tokenSetupClient && ( + + )} +
+

+ {loading + ? 'Checking activity…' + : verificationUnavailable + ? 'Activity is unavailable' + : verificationConnection?.last_used_at + ? 'Deft received a request' + : !tokenSetupClient && !selectedGrantId + ? 'Choose your connection to verify' + : 'Waiting for the first request'} +

+

+ {verificationUnavailable + ? 'We could not refresh the activity. Retry to check the latest status.' + : verificationConnection?.last_used_at + ? `Last used ${formatDate(verificationConnection.last_used_at)}. Review the recorded action to confirm it is the one you expected.` + : 'Completing setup does not confirm connectivity. Run the prompt below in your app, then check again.'} +

+ {verificationConnection && } +
- ))} -
-
Supported remote scopes
-
- {(remote?.scopes ?? AVAILABLE_SCOPES).map((scope) => )} +
+
+

Try this in your app

+ +
+

+ {prompt} +

+
+ Still not connecting? +
    +
  • Check the server URL and your app’s connection status.
  • +
  • + {tokenSetupClient + ? 'Return to Connect and make sure the complete bearer token was copied into the configuration.' + : 'Finish authorization in your app, then refresh and select the new connection above.'} +
  • +
  • Check the permissions if the connection works but a specific action is denied.
  • +
+
+ )} + +
+ + {setupStep === 2 && selectedClientOption.setupKind === 'agent' ? ( + + Open Agent Employees + + ) : setupStep < 3 ? ( + + ) : ( +
+ + +
+ )}
- )} -
+ + )} -
+
- - {historyOpen && ( -
- {!history || historyCount === 0 ? ( -

No revoked connections yet.

- ) : ( - <> - {history.revoked_tokens.length > 0 && ( -
-
- Personal tokens -
-
- {history.revoked_tokens.map((token) => ( -
-
-
-
{token.name}
-
- {token.token_prefix}... / revoked {formatDate(token.revoked_at)} / last used {formatDate(token.last_used_at)} -
-
- - revoked - -
-
- {token.scopes.map((scope) => ( - {scope} - ))} -
- -
- ))} -
-
- )} - - {history.revoked_grants.length > 0 && ( -
-
- AI app connections -
-
- {history.revoked_grants.map((grant) => ( -
-
-
-
{grant.app_name}
-
- {grant.connector_profile} / revoked {formatDate(grant.revoked_at)} / last used {formatDate(grant.last_used_at)} -
-
- - revoked - -
-
- {grant.scopes.map((scope) => ( - {scope} - ))} -
- -
- ))} -
-
- )} - + {advancedOpen && ( +
+ {loadFailures.includes('Connector settings') && ( +
+

Connector metadata is unavailable.

+ +
)} + {[['MCP endpoint', endpoint || undefined], ...remoteRows].map(([label, value]) => ( +
+
+

{label}

+ + {value ?? 'Unavailable'} + +
+ {value && } +
+ ))} + +
+ Memory context +
+ {CONTEXT_PACKET_CARDS.map((card) => ( +
+
{card.title}
+
+ {card.detail} +
+
+ ))} +
+
)}
diff --git a/apps/web/src/app/(app)/settings/page.tsx b/apps/web/src/app/(app)/settings/page.tsx index d237ea5f..ba9df538 100644 --- a/apps/web/src/app/(app)/settings/page.tsx +++ b/apps/web/src/app/(app)/settings/page.tsx @@ -18,16 +18,16 @@ import { Users, Workflow, } from 'lucide-react'; -import { APPS_ENABLED } from '@/lib/feature-flags'; -const overviewCards = [ - { title: 'Profile', body: 'Identity, status, notifications, and security.', href: '/settings/profile', icon: UserRound, admin: false }, - { title: 'People & teams', body: 'Membership, access, ownership, and team context.', href: '/settings/members', icon: Users, admin: true }, - { title: 'Modules', body: 'Install workspace modules and govern their agent access.', href: '/settings/modules', icon: Boxes, admin: true }, - ...(APPS_ENABLED ? [{ title: 'Apps', body: 'Expand Deft with locally authored declarative Apps.', href: '/settings/apps', icon: Boxes, admin: true }] : []), - { title: 'Calendar', body: 'Bring external calendar context into Deft or subscribe to Deft events.', href: '/settings/calendar', icon: CalendarDays, admin: false }, - { title: 'AI connections', body: 'Connect Codex, Claude, ChatGPT, and other MCP clients.', href: '/settings/mcp-access', icon: Workflow, admin: false }, - { title: 'Agent employees', body: 'Operate shared agents as accountable members of the workspace.', href: '/settings/agent-employees', icon: Bot, admin: true }, +const overviewLinks = [ + { href: '/settings/profile', icon: UserRound }, + { href: '/settings/members', icon: Users }, + { href: '/settings/teams', icon: Users }, + { href: '/settings/apps', icon: Boxes }, + { href: '/settings/modules', icon: Boxes }, + { href: '/settings/calendar', icon: CalendarDays }, + { href: '/settings/mcp-access', icon: Workflow }, + { href: '/settings/agent-employees', icon: Bot }, ] as const; export default function SettingsPage() { @@ -37,6 +37,10 @@ export default function SettingsPage() { const isAdmin = user?.role === 'owner' || user?.role === 'admin'; const groups = getSettingsNavGroups(user?.role ?? 'member'); const availableItems = groups.flatMap((group) => group.items); + const overviewCards = overviewLinks.flatMap(({ href, icon }) => { + const item = availableItems.find((candidate) => candidate.href === href); + return item ? [{ title: item.name, body: item.description, href, icon }] : []; + }); const results = useMemo(() => { const normalized = query.trim().toLowerCase(); if (!normalized) return []; @@ -99,7 +103,7 @@ export default function SettingsPage() {

Common settings

- {overviewCards.filter((card) => !card.admin || isAdmin).map(({ title, body, href, icon: Icon }) => ( + {overviewCards.map(({ title, body, href, icon: Icon }) => (

{title}

{body}

@@ -112,8 +116,8 @@ export default function SettingsPage() { {isAdmin && (
-

Advanced administration

Automation, recovery, providers, governance, and developer access live in the Advanced section of the sidebar.

- Open task settings +

Developer & operator

Service credentials and self-hosted source information are in Developer & operator. Task rules and recovery are in Work management.

+ Service API access
)} diff --git a/apps/web/src/app/(app)/settings/profile/page.tsx b/apps/web/src/app/(app)/settings/profile/page.tsx index 816854f4..bf800fdd 100644 --- a/apps/web/src/app/(app)/settings/profile/page.tsx +++ b/apps/web/src/app/(app)/settings/profile/page.tsx @@ -4,6 +4,7 @@ import { useRef, useEffect, useMemo, useState } from 'react'; import { api } from '@/lib/api'; import { useAuth } from '@/lib/auth-context'; import { Clock, KeyRound, Loader2, Save, X } from 'lucide-react'; +import { SettingsSectionNav } from '@/components/settings-section-nav'; import { BrowserNotificationSettings } from '@/components/browser-notification-settings'; const COMMON_TIMEZONES = [ @@ -80,6 +81,7 @@ function joinList(value: string[] | null | undefined): string { } export default function ProfileSettingsPage() { + const [section, setSection] = useState<'identity' | 'preferences' | 'security'>('identity'); const { user, refreshUser, replaceUser, logout } = useAuth(); const fileInputRef = useRef(null); const [name, setName] = useState(''); @@ -249,21 +251,27 @@ export default function ProfileSettingsPage() { return (
-
+
-

Account

-

- My profile +

+ Profile

-

+

Shape how teammates understand your role, availability, and collaboration preferences.

-
+ + + +
+ {error &&
{error}
} + {saveMessage &&
{saveMessage}
} + +
+ +
+
- - -
- {error &&
{error}
} - {saveMessage &&
{saveMessage}
} - -
- +
); diff --git a/apps/web/src/app/(app)/settings/settings.module.css b/apps/web/src/app/(app)/settings/settings.module.css new file mode 100644 index 00000000..59e508ff --- /dev/null +++ b/apps/web/src/app/(app)/settings/settings.module.css @@ -0,0 +1,47 @@ +.settings { + display: contents; + --border: color-mix(in srgb, var(--text-primary) 17%, transparent); + --border-default: var(--border); + --border-strong: color-mix(in srgb, var(--text-primary) 28%, transparent); + --settings-action: #7056dc; +} + +.settings :is(button, a, input, textarea, select, summary):focus-visible { + outline: 2px solid var(--primary); + outline-offset: 3px; +} + +.settings :is(input, textarea, select) { + max-width: 100%; + accent-color: var(--accent); +} + +.settings :is(input:not([type='checkbox']):not([type='radio']):not([type='file']), select) { + min-height: 2.5rem; +} + +.settings textarea { + line-height: 1.6; +} + +.settings :is(button, summary) { + transition: box-shadow 140ms ease, background-color 140ms ease; +} + +.settings button:not(:disabled):hover { + box-shadow: inset 0 0 0 100px color-mix(in srgb, var(--text-primary) 5%, transparent); +} + +.settings button:disabled { + cursor: not-allowed; +} + +.settings :is(h1, h2, h3) { + text-wrap: balance; +} + +@media (prefers-reduced-motion: reduce) { + .settings :is(button, summary) { + transition: none; + } +} diff --git a/apps/web/src/app/(app)/settings/tags/page.tsx b/apps/web/src/app/(app)/settings/tags/page.tsx index fe822457..97b8a1a3 100644 --- a/apps/web/src/app/(app)/settings/tags/page.tsx +++ b/apps/web/src/app/(app)/settings/tags/page.tsx @@ -156,22 +156,23 @@ export default function TagsPage() { {/* Create tag */} {creating && (
-
-
+
+
setNewName(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') handleCreate(); if (e.key === 'Escape') setCreating(false); }} placeholder="Tag name (e.g. launch, q3-planning)" - className="flex-1 h-9 px-3 rounded-lg text-[13px] outline-none" + aria-label="Tag name" + className="col-span-2 min-w-0 w-full flex-1 h-9 px-3 rounded-lg text-[13px] outline-none" style={{ background: 'var(--input-bg)', color: 'var(--foreground)', border: '1px solid var(--input-border)' }} /> -
{TAG_COLORS.map(c => ( - )}
@@ -171,7 +171,7 @@ export default function WorkflowsPage() {

- New workflow + New task rule

@@ -269,7 +269,7 @@ export default function WorkflowsPage() { style={{ background: 'var(--surface-container-low)', border: '1px dashed var(--border-default, var(--outline-variant))' }} > -

No workflows yet.

+

No task rules yet.

Start with a small rule like adding a label or notifying a lead when work moves to review.

diff --git a/apps/web/src/components/settings-section-nav.tsx b/apps/web/src/components/settings-section-nav.tsx new file mode 100644 index 00000000..6a23d3a6 --- /dev/null +++ b/apps/web/src/components/settings-section-nav.tsx @@ -0,0 +1,34 @@ +'use client'; + +/** Section buttons keep each form mounted so switching sections preserves drafts. */ +export function SettingsSectionNav({ + label, + sections, + value, + onChange, +}: { + label: string; + sections: readonly { id: T; label: string }[]; + value: T; + onChange: (value: T) => void; +}) { + return ( + + ); +} diff --git a/apps/web/src/components/settings-steps.tsx b/apps/web/src/components/settings-steps.tsx new file mode 100644 index 00000000..6af0533e --- /dev/null +++ b/apps/web/src/components/settings-steps.tsx @@ -0,0 +1,14 @@ +export function SettingsSteps({ steps, current }: { steps: readonly string[]; current: number }) { + return ( + + ); +} diff --git a/apps/web/src/components/sidebar.tsx b/apps/web/src/components/sidebar.tsx index 354c7e85..9b9f8dd8 100644 --- a/apps/web/src/components/sidebar.tsx +++ b/apps/web/src/components/sidebar.tsx @@ -696,7 +696,7 @@ function SettingsSidebarContent({ onNav }: { onNav?: () => void }) { }} aria-expanded={advancedOpen} > - Advanced + {advancedGroup.label} {advancedOpen && ( diff --git a/apps/web/src/lib/settings-navigation.test.ts b/apps/web/src/lib/settings-navigation.test.ts index 1b22ebe0..c9e4f84e 100644 --- a/apps/web/src/lib/settings-navigation.test.ts +++ b/apps/web/src/lib/settings-navigation.test.ts @@ -2,25 +2,29 @@ import test from 'node:test'; import assert from 'node:assert/strict'; import { getSettingsNavGroups, isSettingsItemActive } from './settings-navigation'; -test('members see only personal workspace and personal connection settings', () => { - const items = getSettingsNavGroups('member').flatMap((group) => group.items); - assert.deepEqual(items.map((item) => item.name), ['General', 'Profile', 'License & source', 'Calendar', 'Connections']); - assert.equal(items.some((item) => item.href === '/settings/api-access'), false); +test('members and guests see personal settings without admin destinations', () => { + for (const role of ['member', 'guest'] as const) { + const items = getSettingsNavGroups(role).flatMap((group) => group.items); + assert.deepEqual(items.map((item) => item.href), ['/settings', '/settings/profile', '/settings/mcp-access', '/settings/calendar', '/license']); + } }); -test('owners get module administration as a primary workspace destination', () => { - const groups = getSettingsNavGroups('owner'); - const primary = groups.filter((group) => !group.advanced).flatMap((group) => group.items); - const advanced = groups.find((group) => group.advanced); - - assert.equal(primary.length, 9); - assert.ok(primary.some((item) => item.href === '/settings/modules')); - assert.ok(advanced); - assert.ok(advanced.items.some((item) => item.name === 'Mention groups')); - assert.ok(advanced.items.some((item) => item.name === 'API access')); +test('administrators get distinct personal, workspace and service connection destinations', () => { + for (const role of ['owner', 'admin'] as const) { + const groups = getSettingsNavGroups(role); + const groupFor = (href: string) => groups.find((group) => group.items.some((item) => item.href === href)); + assert.equal(groupFor('/settings/mcp-access')?.label, 'Your account'); + assert.equal(groupFor('/settings/integrations')?.label, 'Agents & AI'); + assert.equal(groupFor('/settings/api-access')?.advanced, true); + assert.equal(groupFor('/settings/modules')?.label, 'Workspace'); + assert.equal(groupFor('/settings/workflows')?.label, 'Work management'); + const hrefs = groups.flatMap((group) => group.items.map((item) => item.href)); + assert.equal(new Set(hrefs).size, hrefs.length); + } }); test('nested settings routes keep their parent navigation item active', () => { assert.equal(isSettingsItemActive('/settings/agent-employees/create', '/settings/agent-employees'), true); assert.equal(isSettingsItemActive('/settings/profile', '/settings'), false); + assert.equal(isSettingsItemActive('/settings/agent-employees', '/settings/agent'), false); }); diff --git a/apps/web/src/lib/settings-navigation.ts b/apps/web/src/lib/settings-navigation.ts index e25f3386..59a673d9 100644 --- a/apps/web/src/lib/settings-navigation.ts +++ b/apps/web/src/lib/settings-navigation.ts @@ -1,3 +1,5 @@ +import { APPS_ENABLED } from './feature-flags'; + export type SettingsRole = 'owner' | 'admin' | 'member' | 'guest'; export type SettingsNavItem = { @@ -18,47 +20,53 @@ const ADMIN_ROLES: SettingsRole[] = ['owner', 'admin']; export const settingsNavGroups: SettingsNavGroup[] = [ { - label: 'Account', - description: 'Your workspace preferences and identity.', + label: 'Your account', + description: 'Your identity, preferences and personal connections.', items: [ - { name: 'General', href: '/settings', description: 'Theme and settings overview.' }, + { name: 'Overview', href: '/settings', description: 'Find settings and change your appearance.' }, { name: 'Profile', href: '/settings/profile', description: 'Identity, status, notifications, and security.' }, - { name: 'License & source', href: '/license', description: 'View Deft\'s AGPL license and Corresponding Source.' }, + { name: 'Personal AI connections', href: '/settings/mcp-access', description: 'Connect Codex, Claude or another AI client acting as you.' }, + { name: 'Calendar connections', href: '/settings/calendar', description: 'Manage your external calendar subscriptions and personal Deft feed.' }, ], }, { label: 'Workspace', - description: 'People, teams, and shared time.', + description: 'People and tools shared by your workspace.', items: [ { name: 'People', href: '/settings/members', description: 'Invite people and manage workspace access.', roles: ADMIN_ROLES }, - { name: 'Teams', href: '/settings/teams', description: 'Organize people around ownership and linked work.', roles: ADMIN_ROLES }, - ...(APPS_ENABLED ? [{ name: 'Apps', href: '/settings/apps', description: 'Install and govern workspace Apps.', roles: ADMIN_ROLES }] : []), - { name: 'Modules', href: '/settings/modules', description: 'Install and govern workspace modules.', roles: ADMIN_ROLES }, - { name: 'Calendar', href: '/settings/calendar', description: 'Connect calendars with self-hostable ICS feeds.' }, + { name: 'Teams', href: '/settings/teams', description: 'Manage team membership and linked work.', roles: ADMIN_ROLES }, + ...(APPS_ENABLED ? [{ name: 'Apps', href: '/settings/apps', description: 'Manage installed Apps and their access.', roles: ADMIN_ROLES }] : []), + { name: 'Modules', href: '/settings/modules', description: 'Manage standalone Modules and collection agent access.', roles: ADMIN_ROLES }, + { name: 'Mention groups', href: '/settings/groups', description: 'Reusable @mention lists for chat; separate from team access.', roles: ADMIN_ROLES }, ], }, { - label: 'AI & Connections', - description: 'Shared agents and personal AI apps.', + label: 'Agents & AI', + description: 'Shared agents, model configuration and workspace policy.', items: [ - { name: 'Agent employees', href: '/settings/agent-employees', description: 'Manage agents that work alongside the team.', roles: ADMIN_ROLES }, - { name: 'Connections', href: '/settings/mcp-access', description: 'Connect Codex, Claude, ChatGPT, or another MCP client.' }, + { name: 'Agent employees', href: '/settings/agent-employees', description: 'Manage shared agents, their access and runtime setup.', roles: ADMIN_ROLES }, + { name: 'AI configuration', href: '/settings/ai', description: 'Configure model providers, search and voice features.', roles: ADMIN_ROLES }, + { name: 'Tool connections', href: '/settings/integrations', description: 'External MCP tool servers used by workspace agents and Apps.', roles: ADMIN_ROLES }, + { name: 'Policies & audit', href: '/settings/agent', description: 'Workspace trust defaults and action receipts.', roles: ADMIN_ROLES }, ], }, { - label: 'Advanced', - description: 'Specialist workspace, automation, AI, and developer controls.', - advanced: true, + label: 'Work management', + description: 'Reusable work, task rules and recovery.', items: [ - { name: 'Mention groups', href: '/settings/groups', description: 'Reusable @mention lists for chat.', roles: ADMIN_ROLES }, - { name: 'Tags', href: '/settings/tags', description: 'Review workspace labels and usage counts.', roles: ADMIN_ROLES }, - { name: 'Task templates', href: '/settings/library', description: 'Reusable task templates and work packs.', roles: ADMIN_ROLES }, - { name: 'Automations', href: '/settings/workflows', description: 'Task status-change rules.', roles: ADMIN_ROLES }, + { name: 'Task templates', href: '/settings/library', description: 'Reusable task sets for projects.', roles: ADMIN_ROLES }, + { name: 'Task rules', href: '/settings/workflows', description: 'Rules triggered by task status changes. App schedules live in Apps.', roles: ADMIN_ROLES }, + { name: 'Tags', href: '/settings/tags', description: 'Workspace labels and usage counts.', roles: ADMIN_ROLES }, { name: 'Project recovery', href: '/settings/projects', description: 'Restore recently deleted projects.', roles: ADMIN_ROLES }, - { name: 'Agent tool servers', href: '/settings/integrations', description: 'External MCP tools available to agents.', roles: ADMIN_ROLES }, - { name: 'AI providers', href: '/settings/ai', description: 'Model providers and local endpoints.', roles: ADMIN_ROLES }, - { name: 'Agent governance', href: '/settings/agent', description: 'Workspace trust defaults, activity, and audit.', roles: ADMIN_ROLES }, - { name: 'API access', href: '/settings/api-access', description: 'Service keys for scripts and runtimes.', roles: ADMIN_ROLES }, + ], + }, + { + label: 'Developer & operator', + description: 'Service credentials and self-hosted source information.', + advanced: true, + items: [ + { name: 'Service API access', href: '/settings/api-access', description: 'API keys for scripts and service runtimes.', roles: ADMIN_ROLES }, + { name: 'License & source', href: '/license', description: 'AGPL license and Corresponding Source.' }, ], }, ]; @@ -78,4 +86,3 @@ export function isSettingsItemActive(pathname: string, href: string) { if (href === '/settings') return pathname === href; return pathname === href || pathname.startsWith(`${href}/`); } -import { APPS_ENABLED } from './feature-flags'; diff --git a/docs/superpowers/audits/2026-09-09-settings-review-passes.md b/docs/superpowers/audits/2026-09-09-settings-review-passes.md new file mode 100644 index 00000000..5c29e477 --- /dev/null +++ b/docs/superpowers/audits/2026-09-09-settings-review-passes.md @@ -0,0 +1,83 @@ +# Settings review passes — 2026-09-09 + +Scope: visual and interaction review of the current Settings implementation on +`codex/settings-visual-polish`, using the localhost:3025 app and synthetic, +read-only API fixture. This is not a production integration certification. + +## Pass 1: route inventory and desktop layout + +Visited all 18 top-level Settings routes at 1440 CSS px. Pages loaded without a +rendered application crash or page-level horizontal overflow. Profile's initial +automated heading observation matched an Overview card during navigation; +the saved Profile screenshot and subsequent direct inspection verified the page. + +| Route | Desktop | Mobile initial layout (390 CSS px) | +| --- | --- | --- | +| `/settings` | Reviewed | Reviewed | +| `/settings/profile` | Reviewed | Reviewed | +| `/settings/mcp-access` | Reviewed | Reviewed | +| `/settings/calendar` | Reviewed | Reviewed | +| `/settings/members` | Reviewed | Reviewed | +| `/settings/teams` | Reviewed | Reviewed | +| `/settings/apps` | Reviewed | Reviewed | +| `/settings/modules` | Reviewed | Reviewed | +| `/settings/groups` | Reviewed | Reviewed | +| `/settings/agent-employees` | Reviewed | Reviewed | +| `/settings/ai` | Reviewed | Reviewed | +| `/settings/integrations` | Reviewed | Reviewed | +| `/settings/agent` | Reviewed | Reviewed | +| `/settings/library` | Reviewed | Missing title fixed | +| `/settings/workflows` | Reviewed | Narrow action fixed | +| `/settings/tags` | Reviewed | Initial layout fits; form overflow fixed | +| `/settings/projects` | Reviewed | Reviewed | +| `/settings/api-access` | Reviewed | Narrow action fixed | + +## Pass 2: mobile screenshots + +Saved and inspected initial screenshots for all 18 routes. Page-level width alone +was insufficient: a nested horizontal scrolling container hid overflowing tag-form +controls. The follow-up check measured individual visible control bounds too. + +Evidence: `tmp/preview-evidence/audit-mobile-0.png` through `audit-mobile-17.png`, +three `audit-sheet-*.png` contact sheets, and `settings-audit.json`. These ignored +local artifacts use sample data; they are not checked into the repository. + +## Pass 3: forms, secondary routes, and fixes + +Opened service-key, task-rule, tag, group, team and invitation forms at phone width. +Inspected agent creation and the staged Contacts App detail route. No invitations, +credentials, App activation, trust changes or external writes were performed. + +Reproduced and fixed: + +1. Task templates used a compact PageHeader without an alternative mobile title. + Removed compact mode; the title is now visibly rendered at 390px. +2. Task-rule creation action was squeezed into a tall, narrow label by the heading + row. Stack the header on narrow screens and keep the action from shrinking. +3. Service API creation action had the same problem. Applied the same bounded fix. +4. Tag creation's Create and Cancel controls extended to approximately 397px and + 441px on a 390px viewport. Use a two-row mobile grid and a shrinkable input. + Give the input, cancel control and colour buttons accessible names and expose + the selected colour with aria-pressed. + +Fresh recheck: zero offscreen tag controls at 390px and 320px; colour selection +updates aria-pressed; cancel closes the form. Inspected corrected screenshots for +all four pages: `audit-fixed-{tags,templates,rules,service}-mobile.png`. + +Web typecheck, focused ESLint for the four changed pages, three Settings navigation +tests, and git diff whitespace checks passed. No backend contracts changed. + +## Remaining evidence gaps + +- The four employee record routes (detail, developer, heartbeats, webhooks) need + populated employee records; this fixture has none. Their healthy rendered states + were not certified in this pass. +- Empty lists do not prove populated tables, long records, pagination or every + dialog state. The staged App detail is one sample, not lifecycle certification. +- Save persistence, real OAuth/MCP connections, role-based runtime authorization, + screen-reader use, browser zoom and exhaustive light-theme states remain outside + this pass. Previous light-theme inspection was representative, not exhaustive. +- Some existing forms still use placeholder-only labels and small controls. The + fixes above are specific findings, not a claim of complete accessibility. + +PR #325 remains stacked on #324 and unmerged for user review. diff --git a/docs/superpowers/plans/2026-09-09-settings-implementation-loops.md b/docs/superpowers/plans/2026-09-09-settings-implementation-loops.md new file mode 100644 index 00000000..59c50575 --- /dev/null +++ b/docs/superpowers/plans/2026-09-09-settings-implementation-loops.md @@ -0,0 +1,97 @@ +# Settings implementation loops + +The Settings exploration identified a structural problem: personal clients, shared +workspace tools, operator credentials and employee operations are presented as +overlapping destinations. The implementation should make the owner and purpose of +each setting clear while retaining existing permissions, API payloads and routes. + +## Loop 1: navigation and focused management surfaces + +- Group navigation into Your account, Workspace, Agents & AI, Work management, + and Developer & operator. Derive overview cards from the same role-filtered + navigation definitions. Keep all existing URLs. +- Open Apps on a searchable installed list. Give each App a detail URL at + `/settings/apps/[id]`, retaining its existing review and lifecycle controls. + Keep package inspection and developer pairing under Add or build an App. +- Put active personal connections before an expandable Add connection flow. + Keep token scopes, grants, revocation and archived activity unchanged. +- Separate Calendar into Connected calendars and Share Deft calendar; AI into + Providers, Model routing, Search and Voice; Profile into Identity, + Availability & notifications, and Security. +- Keep section contents mounted to retain unsaved drafts. Profile and preferences + still share their existing save request; password changes keep their independent + handler. No permission model, database or runtime changes belong in this loop. + +Acceptance: role/navigation tests, web typecheck and lint, rendered desktop/mobile +inspection, search and detail navigation, and draft retention across section +changes. Local UI checks use synthetic data and do not certify production writes. + +Validation on 2026-09-09: all three navigation tests passed; web typecheck and full +web lint passed, followed by focused lint after final edits. The local Next.js +renderer was inspected at 1440×900 and 390×844, in light and dark themes. +Connection inventory/setup, App search (including no matches), App detail refresh +and return navigation, and Profile/Calendar/model-routing draft retention were +exercised. Password changes, token issuance, App activation and real connector +calls were not executed. The fixture intentionally omitted realtime and dashboard +data; this is UI evidence, not a database-backed integration run or release gate. + +## Connection layout regression follow-up (2026-09-09) + +Reproduced the reported Claude Code/custom-permissions overflow in the local +renderer: a 942px setup grid had 1170px of content. The CLI command's intrinsic +width expanded the main track and pushed the help aside outside the parent card. +Zero-minimum grid tracks and shrinkable children now contain the command's own +horizontal scroller. The main form receives two thirds of the available width. +Client names wrap instead of truncating; selection buttons expose pressed state, +and the token-name input has an accessible name and a shrinkable grid track. + +A failed OAuth-readiness response also left the connector URL saying Loading +indefinitely. Unavailable readiness now has explicit status and a retry action. +The existing production browser smoke assumed setup was initially expanded; +it now checks the connection inventory, opens Add connection, and checks Claude +Code custom permissions for card overflow at 1440, 1024, 768 and 390px. + +Fresh local evidence: 54 rendered client/preset/width combinations, including all +seven clients and all four presets for each token client at 1440 and 390 CSS px; +all clients plus Claude Code custom scopes also checked at 1025 and 768 CSS px. +No setup-grid or section overflow remained. Long command blocks scroll internally. +Unchecked all scopes (Generate token disabled), reselected read:tasks (enabled), +and retained the name and selection through closing/reopening Add connection. +Checked config-copy feedback, rejected token-request recovery, OAuth retry, +advanced endpoint expansion, and empty connection history. Desktop/mobile +screenshots and the 54 measurements are local artifacts under +`tmp/preview-evidence/`. Web typecheck, full web lint, three navigation tests, +smoke-script syntax and diff whitespace checks passed. + +Limits: localhost is a synthetic UI fixture. It does not issue real credentials, +persist mutations, or complete external OAuth. The prior production CI run passed +login, chat/task writes and Inbox approval, then failed on the obsolete setup +heading expectation corrected above. The updated production smoke requires a new +CI run. Dependency Audit separately reported eight vulnerabilities (two critical, +three high, three moderate); dependency remediation and release clearance remain +open. This follow-up does not certify all product behavior or Gate G. + +## Next loops + +1. **Module ownership.** The API rejects enable/disable and manifest changes to + App-owned Modules, but the module installation view currently omits ownership. + Add an explicit organization-scoped ownership field to the read contract and + route lifecycle management to the owning App. Preserve collection agent-access + policy controls and standalone Module management. Do not infer ownership from + manifest declarations: a staged App can request a Module it does not own. +2. **Canonical employee management.** Governance currently owns clone, save as + template, trust escalation and turn/receipt inspection that the employee list + does not expose. Move these into employee detail before removing the duplicate + roster. Retain developer/runtime setup links, confirmations and receipt checks. +3. **Foundation evidence.** Mandatory current-candidate boundary checks, public + App Kit distribution and explicit worker restart/restore evidence remain open. + A locally packed kit is not public distribution. A Settings PR is not Track A + recertification or Gate G clearance. +4. **Track B isolation.** The hostile static UI experiment blocked parent DOM, + cookie/storage access and fetch, but sandboxed frame self-navigation still + reached a local sink. Resolve that no-egress gap before freezing the manifest + and bridge contract or claiming an isolated Email Lite shell. + +Each implementation loop should produce a reviewable PR with fresh evidence. +PRs must remain unmerged until the user has reviewed them. Tracks B, C, D and +Gate G are not complete as a result of these Settings changes. diff --git a/docs/superpowers/plans/2026-09-09-settings-maturity-program.md b/docs/superpowers/plans/2026-09-09-settings-maturity-program.md new file mode 100644 index 00000000..1849e75f --- /dev/null +++ b/docs/superpowers/plans/2026-09-09-settings-maturity-program.md @@ -0,0 +1,242 @@ +# Settings maturity program + +Status: active. User authorized iterative implementation and PR creation; never +merge or enable auto-merge before user review. This is a delivery checkpoint, not +a claim that Settings is complete. Resume from the first unfinished milestone. + +## Workspace and existing evidence + +Work in `C:/tmp/deft-settings-structure`; current implementation branch is +`codex/settings-connection-flow`, based on `codex/settings-structure` at 5f6f0d86. +PR #323 contains the first structural pass and connection overflow repair. +Preserve the original worktree and unrelated changes. Keep milestones separately +reviewable; use explicitly based follow-up branches/PRs for subsequent features, +and record their base and dependency rather than silently merging the first PR. + +Local renderer: http://localhost:3025. API fixture: localhost:4191. +The fixture does not persist changes or issue credentials. It cannot establish +database-backed or external integration acceptance. Existing UI evidence and +foundation boundaries are in `2026-09-09-settings-implementation-loops.md`. + +## Definition of the outcome + +Users can locate a setting, understand who and what it affects, perform the task, +and verify its outcome. Main surfaces prioritize the next useful action. Existing +authorization, API payloads and lifecycle operations remain intact unless a +separately reviewed contract change is required. No fabricated connection health, +success, role access or release certification. + +## Route inventory confirmed from source + +| Destination | Existing route | Intended pattern | +| --- | --- | --- | +| Overview | /settings | Role-filtered searchable directory | +| Profile | /settings/profile | Identity/preferences form and separate security actions | +| Personal AI connections | /settings/mcp-access | Managed list, guided setup, connection management | +| Calendar connections | /settings/calendar | Connection list and feed-sharing configuration | +| People | /settings/members | Member/invitation list and role management | +| Teams | /settings/teams | Managed membership list/detail | +| Apps | /settings/apps, /settings/apps/[id] | Installed list, detail, governed setup | +| Modules | /settings/modules | Owned/standalone list, collection policy configuration | +| Mention groups | /settings/groups | Reusable mention lists; distinct from access membership | +| Agent employees | /settings/agent-employees | Canonical roster and employee detail | +| Employee setup | /settings/agent-employees/create | Guided setup | +| Employee operations | /settings/agent-employees/[id], /webhooks, /heartbeats, /developer beneath that detail | Contextual operational detail | +| AI configuration | /settings/ai | Provider readiness, model routing, search, voice | +| Tool connections | /settings/integrations | Shared MCP-server management | +| Policies and audit | /settings/agent | Separate policy configuration and evidence inspection | +| Task templates | /settings/library | Reusable template list/detail | +| Task rules | /settings/workflows | Rule list/editor | +| Tags | /settings/tags | Compact labels list with usage | +| Project recovery | /settings/projects | Deleted-resource list and restore action | +| Service API access | /settings/api-access | Credential lifecycle management | + +This inventory establishes destinations, not a completed control audit. Before +rewriting each page, enumerate its handlers, API calls, role conditions and +secondary actions. Record their replacement locations. Inspect server contracts +for consequences and authorization; frontend labels alone are insufficient. + +## Shared interaction contract + +- One page title and concise purpose; avoid decorative category badges and + repeated explanations. Use the existing theme tokens and typography. +- Forms use readable constrained widths; managed lists may use wider layouts. + Setting rows contain label, explanation, current value/control and local feedback. +- Cards denote independent resources or distinct tasks, not every nested paragraph. +- Explicit Save for related form fields. Preserve drafts while changing sections. + Show unsaved changes and intercept discard where necessary. Do not mix implicit + autosave with explicit saves without an obvious distinction. +- Action feedback appears adjacent to the originating control and is announced + accessibly. Pending requests prevent duplicates; failures retain input and offer + recovery. Never announce success before confirmation. +- States: loading, empty, ready, partial configuration, unavailable, denied, saving, + saved and failed. Resource health requires actual backend evidence. +- Keyboard focus stays visible and follows meaningful setup transitions. Steps + have labels and current-step semantics; inputs have persistent accessible labels. +- At 390px and narrower, secondary content follows the main task. Test 200% zoom, + long names, long commands and large lists. Internal code scrolling must not + expand parent cards. Use bounded columns with zero minimum widths. +- Keep all role/feature-filtered destinations aligned between navigation, overview + and search. Do not expose hidden admin metadata through search results. + +## Milestones and completion evidence + +### 1. Reference connection experience — next implementation + +Inventory is the initial state. Setup has four explicit stages: client, access, +connect, verify. OAuth clients review access on the actual authorization screen; +do not imply local presets govern an external grant. Shared employees lead to the +employee setup destination. Token clients retain the existing scope contracts. + +Use a compact client picker. Access presents a recommended set and expandable +individual controls. Connect shows one client's instructions and local copy/error +feedback. Verification distinguishes instructions from observed activity. Preserve +drafts on Back/Next and setup close; client changes must not silently leave a token +with misleading instructions or lose an unacknowledged one-time credential. + +Extract reusable step/section/feedback patterns only when this reference uses +them. Do not create an unused component library. Include future list/detail +management without deleting revocation, grants or history. + +Acceptance: all client branches; all permission presets; empty scopes; back/next; +draft retention; clipboard failure; request failure/retry; token once-only display; +actual verification state; keyboard and mobile. Add regression coverage against +observable behavior, and update production smoke to follow the new flow. + +### 2. Apps, Modules and employee ownership + +Expose organization-scoped module ownership in the read contract before routing +management to its owner. Preserve standalone actions and collection access policy. +Audit Governance-only employee actions (clone, template, trust and receipts) before +consolidation. Apply architecture-gate for contract/trust changes. Separate schema +or API work from presentation when it improves review and rollback. + +### 3. Shared patterns across remaining pages + +Apply the validated reference patterns to Profile, Calendar and AI, then People, +Teams, groups, tool connections, policy/audit, templates, rules, tags, recovery and +service access. Track each page's control inventory and verification rather than +claiming a blanket pass from page-load screenshots. + +### 4. Integrated acceptance and polish + +Use a disposable database-backed workspace, representative roles and realistic +records. Verify persistence, denied actions, recoverable failures, browser history, +deep links, refresh, keyboard, zoom and responsive layouts. Test live connector +flows only within user-authorized scope. Require independent user task validation +before calling usability proven. Resolve relevant CI/security blockers separately. + +## Loop protocol + +Each loop: read this checkpoint and git status; inspect relevant code; implement a +bounded coherent change; reproduce/verify behavior; inspect final diff; commit and +open/update a PR only with fresh evidence. Update this document with completed +work, evidence, exact next action and blockers. Never treat elapsed time or silence +as approval. Continue independent work when external review is pending. No merge, +production deployment, real credential grants or external messages are implied. + +## Current checkpoint + +- Completed: existing route inventory and shared interaction specification above. +- Existing repair: PR #323, commit 6e0ec97b, 54 rendered connection states verified; + web lint/typecheck/navigation tests passed. Updated production smoke pending. +- Implemented: guided connection setup on `codex/settings-connection-flow`: + compact client selection; access review; client-specific connection instructions; + explicit verification. Shared employee setup exits to its existing destination. + Added reusable SettingsSteps progress with current-step semantics and step focus. + Existing token scope payloads and OAuth permissions are unchanged. New tokens + lock the client, name and scopes, prevent duplicate generation, and require an + explicit saved-token acknowledgement before advancing. Back/Next retains drafts + and the one-time token. Clipboard failures produce local feedback. +- Verification uses the issued token_id against the existing inventory response; + it does not infer connection success from completing instructions or another + token's activity. Contextual memory guidance is expandable. +- Fresh evidence: all seven client branches traversed at 390 and 1440 CSS px, + without visible section overflow; name and custom permissions retained across + steps; rejected issuance kept the Connect step; inert synthetic issuance tested + acknowledgement gating, duplicate prevention, locked client/access controls and + pending verification despite another fixture token having recent use. The fixture + was returned to read-only mode afterward. Typecheck, full web lint, navigation + tests and smoke-script syntax passed. Production smoke now traverses the steps, + checks command containment and name retention; CI execution remains pending. +- Screenshots: `tmp/preview-evidence/guided-access-desktop.png` and + `guided-connect-mobile.png`. These are fixture-based visual evidence only. +- Whole-page follow-through (PR #324, stacked on #323): replaced the management + dashboard with a searchable unified token/authorization list, expandable access + and activity, inline revoke confirmation, and restrained history/developer + disclosures. Setup is a separate view with compact client rows, a plain-language + access selector, focused credential instructions and connection-specific checks. + Cancelling preserves drafts; finishing clears the acknowledged credential. + Partial request failures retain the last inventory with an explicit warning; + history and metadata failures have distinct retry states. Verification prompts + follow the selected connection's actual permissions. Copy feedback is local. +- Fresh whole-page evidence: seven client paths at 390 and 1440 CSS px without + section overflow; management and expanded revoke confirmation also checked at + 320 px. Inspected dark desktop/mobile and light desktop/reflow layouts. Tested + search/clear, empty state, partial load failures/recovery, token and grant revoke, + failed revoke/retry, custom-scope validation, draft retention, inert issuance, + acknowledgement/duplicate guards, pending and fixture-observed activity, + grant-specific prompt permissions, and focus on steps/confirm/cancel/finish. + Web typecheck, full web lint, three navigation tests, smoke syntax and diff check + passed. Production smoke now includes issuance/acknowledgement/revoke against + its disposable seeded backend; that updated smoke has not been run locally. +- Current screenshots: `tmp/preview-evidence/connections-whole-desktop.png`, + `connections-whole-mobile.png`, `connections-whole-light.png`, and + `connections-access-desktop.png` / `connections-access-mobile.png`. + All are synthetic fixture evidence, not proof of OAuth or persistence. Browser + zoom and screen-reader acceptance remain unverified; narrow reflow is not a zoom + test. The preview fixture returns to read-only mode after the interaction pass. +- Next: obtain database-backed integration and independent usability evidence for + this page, strengthen zoom/screen-reader acceptance, then apply the patterns to + Profile/Calendar/AI. Module ownership and canonical employee work require their + explicit contract/control audits before implementation. +- Open: dependency audit, real integration evidence, independent usability review. +- Visual polish follow-up: page-local CSS strengthens field/row boundaries and + surface contrast, aligns setup with the page heading, tightens section spacing, + distinguishes heading levels, deepens primary button colour, and adds consistent + hover/focus treatment with reduced-motion support. No API or permission changes. + Inspected desktop dark/light, mobile permissions/connect/expanded details, and + keyboard focus; custom permissions had no section overflow at 390 CSS px. + Fresh web typecheck, focused page lint and diff checks passed. Evidence lives in + `tmp/preview-evidence/polish-*.png`. This is fixture-based visual verification. +- The Settings implementation schedule was deleted at the user's request. Continue + only on direct user instruction; do not recreate it from this checkpoint. +- Other Settings visual pass (`codex/settings-visual-polish`, stacked on #324): + shared Settings-only border tokens, field sizing, keyboard focus, hover and + reduced-motion styles; stronger section navigation on Profile/Calendar/AI. + Profile has a consistent title, wider form and narrower preview, and clearer + save action. Calendar/AI use aligned content widths, larger body text and + consistent headings. No API, authorization or persistence changes. + Verified Profile draft retention across all three sections; Calendar section + switching and mobile add form; all four AI sections at 390px. Inspected desktop + Profile/Calendar/AI and mobile Profile/Calendar/AI/Apps. Desktop route inventory + covered People, Teams, Apps, Modules, groups, tool connections, governance, + templates, rules, tags and recovery without page-level overflow. This is a + shared visual baseline, not a completed individual redesign of every route. + Fixture evidence: `tmp/preview-evidence/settings-*.png`. Persistence and full + mobile/role coverage of the administration pages remain unverified. +- Three review passes completed over 18 top-level routes (desktop, mobile, forms). + Fixed missing mobile Task templates title, squeezed task-rule/service-key actions, + and tag-form overflow with accessible colour/cancel controls. Fresh 320/390px + rechecks, typecheck, focused lint and navigation tests passed. See + `docs/superpowers/audits/2026-09-09-settings-review-passes.md` for exact coverage + and gaps, including the four employee detail routes without fixture records. + +## Merge and demo closeout — 2026-09-09 + +The user approved merging the Settings stack and updating demo.deft.ing. PR #323 +is the consolidated candidate incorporating #324 and #325. Keep the schedule +deleted. Remaining Track B/C/D and Gate G work is outside this UI closeout. + +The final dependency audit reproduced eight advisories. Updated Next.js and its +ESLint config to 16.3.3, the Tiptap family to a patched compatible release, and +Hono, Sharp and js-yaml overrides. The regenerated lockfile passes the full +low-threshold pnpm audit with no known vulnerabilities. Full candidate CI remains +the merge gate; no bypass of image scanning or database-backed browser smoke. + +The public demo routes to the RC1 UI candidate in b3appsprivate20260906; the older +preview.14 container remains separate. Deploy the merged revision through a +separate source checkout, preserve site configuration and existing feature flags, +record the old image, take a stopped database/uploads/configuration backup, and +rehearse the versioned upgrade against a restored database before live cutover. +Verify doctor, connector smoke, build identity and rendered Settings after deploy. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b31fa58..b658354c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,13 +12,13 @@ overrides: engine.io: ^6.6.7 esbuild: ^0.28.1 fast-uri: ^3.1.5 - hono: ^4.12.34 + hono: ^4.13.5 ip-address: ^10.3.1 - js-yaml: ^4.3.1 + js-yaml: ^4.3.2 nanoid: ^3.3.17 postcss: ^8.5.23 qs: ^6.15.2 - sharp: ^0.35.3 + sharp: ^0.35.4 socket.io-parser: ^4.2.7 ws: ^8.21.0 @@ -55,7 +55,7 @@ importers: version: link:../../packages/shared '@hono/node-server': specifier: ^2.0.12 - version: 2.1.1(hono@4.13.2) + version: 2.1.1(hono@4.13.7) bcryptjs: specifier: ^3.0.3 version: 3.0.3 @@ -69,11 +69,11 @@ importers: specifier: 0.8.3 version: 0.8.3 hono: - specifier: ^4.12.34 - version: 4.13.2 + specifier: ^4.13.5 + version: 4.13.7 hono-rate-limiter: specifier: ^0.5.3 - version: 0.5.3(hono@4.13.2) + version: 0.5.3(hono@4.13.7) jsonwebtoken: specifier: ^9.0.3 version: 9.0.3 @@ -133,68 +133,68 @@ importers: specifier: ^4.3.3 version: 4.3.3 '@tiptap/core': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/pm@3.30.4) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/pm@3.31.3) '@tiptap/extension-code-block-lowlight': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/extension-code-block@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)(highlight.js@11.11.1)(lowlight@3.3.0) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/extension-code-block@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)(highlight.js@11.11.1)(lowlight@3.3.0) '@tiptap/extension-details': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/extension-text-style@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)))(@tiptap/pm@3.30.4) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/extension-text-style@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)))(@tiptap/pm@3.31.3) '@tiptap/extension-document': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) '@tiptap/extension-highlight': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) '@tiptap/extension-image': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) '@tiptap/extension-link': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) '@tiptap/extension-paragraph': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) '@tiptap/extension-placeholder': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/extensions@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/extensions@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) '@tiptap/extension-table': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) '@tiptap/extension-table-cell': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/extension-table@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/extension-table@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) '@tiptap/extension-table-header': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/extension-table@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/extension-table@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) '@tiptap/extension-table-row': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/extension-table@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/extension-table@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) '@tiptap/extension-task-item': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) '@tiptap/extension-task-list': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) '@tiptap/extension-text': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) '@tiptap/extension-underline': - specifier: ^3.30.4 - version: 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) + specifier: ^3.30.5 + version: 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) '@tiptap/pm': - specifier: ^3.30.4 - version: 3.30.4 + specifier: ^3.30.5 + version: 3.31.3 '@tiptap/react': - specifier: ^3.30.4 - version: 3.30.4(@floating-ui/dom@1.8.0)(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + specifier: ^3.30.5 + version: 3.31.3(@floating-ui/dom@1.8.0)(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@tiptap/starter-kit': - specifier: ^3.30.4 - version: 3.30.4 + specifier: ^3.30.5 + version: 3.31.3 '@tiptap/suggestion': - specifier: ^3.30.4 - version: 3.30.4(@floating-ui/dom@1.8.0)(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + specifier: ^3.30.5 + version: 3.31.3(@floating-ui/dom@1.8.0)(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) '@types/react-resizable': specifier: ^4.0.0 version: 4.0.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -223,8 +223,8 @@ importers: specifier: ^1.31.0 version: 1.31.0(react@19.2.8) next: - specifier: 16.3.1 - version: 16.3.1(@babel/core@7.29.7)(@types/node@26.2.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + specifier: 16.3.3 + version: 16.3.3(@babel/core@7.29.7)(@types/node@26.2.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) postcss: specifier: ^8.5.23 version: 8.5.26 @@ -302,8 +302,8 @@ importers: specifier: ^9.39.5 version: 9.39.5(jiti@2.7.0) eslint-config-next: - specifier: 16.3.1 - version: 16.3.1(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3) + specifier: 16.3.3 + version: 16.3.3(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3) typescript: specifier: ^6.0.3 version: 6.0.3 @@ -884,7 +884,7 @@ packages: resolution: {integrity: sha512-ELuehkj5VCBdgEw9zs+ivkKwyzzUCSQuE96YmiPvn1ECBoZCczbFXJLeEGMTYjphP6gydh4pHMqEYPVMYUVgQg==} engines: {node: '>=20'} peerDependencies: - hono: ^4.12.34 + hono: ^4.13.5 '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} @@ -910,160 +910,160 @@ packages: resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} engines: {node: '>=18'} - '@img/sharp-darwin-arm64@0.35.3': - resolution: {integrity: sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==} + '@img/sharp-darwin-arm64@0.35.4': + resolution: {integrity: sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==} engines: {node: '>=20.9.0'} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.35.3': - resolution: {integrity: sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==} + '@img/sharp-darwin-x64@0.35.4': + resolution: {integrity: sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==} engines: {node: '>=20.9.0'} cpu: [x64] os: [darwin] - '@img/sharp-freebsd-wasm32@0.35.3': - resolution: {integrity: sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==} + '@img/sharp-freebsd-wasm32@0.35.4': + resolution: {integrity: sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==} engines: {node: '>=20.9.0'} os: [freebsd] - '@img/sharp-libvips-darwin-arm64@1.3.2': - resolution: {integrity: sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==} + '@img/sharp-libvips-darwin-arm64@1.3.3': + resolution: {integrity: sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==} cpu: [arm64] os: [darwin] - '@img/sharp-libvips-darwin-x64@1.3.2': - resolution: {integrity: sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==} + '@img/sharp-libvips-darwin-x64@1.3.3': + resolution: {integrity: sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==} cpu: [x64] os: [darwin] - '@img/sharp-libvips-linux-arm64@1.3.2': - resolution: {integrity: sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==} + '@img/sharp-libvips-linux-arm64@1.3.3': + resolution: {integrity: sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==} cpu: [arm64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-arm@1.3.2': - resolution: {integrity: sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==} + '@img/sharp-libvips-linux-arm@1.3.3': + resolution: {integrity: sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==} cpu: [arm] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-ppc64@1.3.2': - resolution: {integrity: sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==} + '@img/sharp-libvips-linux-ppc64@1.3.3': + resolution: {integrity: sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==} cpu: [ppc64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-riscv64@1.3.2': - resolution: {integrity: sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==} + '@img/sharp-libvips-linux-riscv64@1.3.3': + resolution: {integrity: sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==} cpu: [riscv64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-s390x@1.3.2': - resolution: {integrity: sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==} + '@img/sharp-libvips-linux-s390x@1.3.3': + resolution: {integrity: sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==} cpu: [s390x] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-x64@1.3.2': - resolution: {integrity: sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==} + '@img/sharp-libvips-linux-x64@1.3.3': + resolution: {integrity: sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==} cpu: [x64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linuxmusl-arm64@1.3.2': - resolution: {integrity: sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==} + '@img/sharp-libvips-linuxmusl-arm64@1.3.3': + resolution: {integrity: sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==} cpu: [arm64] os: [linux] libc: [musl] - '@img/sharp-libvips-linuxmusl-x64@1.3.2': - resolution: {integrity: sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==} + '@img/sharp-libvips-linuxmusl-x64@1.3.3': + resolution: {integrity: sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==} cpu: [x64] os: [linux] libc: [musl] - '@img/sharp-linux-arm64@0.35.3': - resolution: {integrity: sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==} + '@img/sharp-linux-arm64@0.35.4': + resolution: {integrity: sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==} engines: {node: '>=20.9.0'} cpu: [arm64] os: [linux] libc: [glibc] - '@img/sharp-linux-arm@0.35.3': - resolution: {integrity: sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==} + '@img/sharp-linux-arm@0.35.4': + resolution: {integrity: sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==} engines: {node: '>=20.9.0'} cpu: [arm] os: [linux] libc: [glibc] - '@img/sharp-linux-ppc64@0.35.3': - resolution: {integrity: sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==} + '@img/sharp-linux-ppc64@0.35.4': + resolution: {integrity: sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==} engines: {node: '>=20.9.0'} cpu: [ppc64] os: [linux] libc: [glibc] - '@img/sharp-linux-riscv64@0.35.3': - resolution: {integrity: sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==} + '@img/sharp-linux-riscv64@0.35.4': + resolution: {integrity: sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==} engines: {node: '>=20.9.0'} cpu: [riscv64] os: [linux] libc: [glibc] - '@img/sharp-linux-s390x@0.35.3': - resolution: {integrity: sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==} + '@img/sharp-linux-s390x@0.35.4': + resolution: {integrity: sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==} engines: {node: '>=20.9.0'} cpu: [s390x] os: [linux] libc: [glibc] - '@img/sharp-linux-x64@0.35.3': - resolution: {integrity: sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==} + '@img/sharp-linux-x64@0.35.4': + resolution: {integrity: sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==} engines: {node: '>=20.9.0'} cpu: [x64] os: [linux] libc: [glibc] - '@img/sharp-linuxmusl-arm64@0.35.3': - resolution: {integrity: sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==} + '@img/sharp-linuxmusl-arm64@0.35.4': + resolution: {integrity: sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==} engines: {node: '>=20.9.0'} cpu: [arm64] os: [linux] libc: [musl] - '@img/sharp-linuxmusl-x64@0.35.3': - resolution: {integrity: sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==} + '@img/sharp-linuxmusl-x64@0.35.4': + resolution: {integrity: sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==} engines: {node: '>=20.9.0'} cpu: [x64] os: [linux] libc: [musl] - '@img/sharp-wasm32@0.35.3': - resolution: {integrity: sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==} + '@img/sharp-wasm32@0.35.4': + resolution: {integrity: sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==} engines: {node: '>=20.9.0'} - '@img/sharp-webcontainers-wasm32@0.35.3': - resolution: {integrity: sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==} + '@img/sharp-webcontainers-wasm32@0.35.4': + resolution: {integrity: sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==} engines: {node: '>=20.9.0'} cpu: [wasm32] - '@img/sharp-win32-arm64@0.35.3': - resolution: {integrity: sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==} + '@img/sharp-win32-arm64@0.35.4': + resolution: {integrity: sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==} engines: {node: '>=20.9.0'} cpu: [arm64] os: [win32] - '@img/sharp-win32-ia32@0.35.3': - resolution: {integrity: sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==} + '@img/sharp-win32-ia32@0.35.4': + resolution: {integrity: sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==} engines: {node: ^20.9.0} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.35.3': - resolution: {integrity: sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==} + '@img/sharp-win32-x64@0.35.4': + resolution: {integrity: sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==} engines: {node: '>=20.9.0'} cpu: [x64] os: [win32] @@ -1106,60 +1106,60 @@ packages: resolution: {integrity: sha512-r3ZZhRjEcfEdKIZnoB1RusNgvHuaBRqfCzV4Gi+5A9yUX0S4HTws/ASWqt13wL4y4I+0rqsWGdA2w7EQXHi3+Q==} engines: {node: '>=19.0.0'} - '@next/env@16.3.1': - resolution: {integrity: sha512-35G3xwkQUb2oETSDjFXGrVugknoayLFBh7vSE+yAcl9IP2zT9wyGwq7297AYHR11kJld807t5f8AJBs6WBzXsQ==} + '@next/env@16.3.3': + resolution: {integrity: sha512-U2eYQRwXj+dsqxV79zFqExDdatnNY/ZWc2nsJU1p/OgT7fd3dXwlF6OjYaFQCfMoeTA19PWq+wVmYgimVA+V+g==} - '@next/eslint-plugin-next@16.3.1': - resolution: {integrity: sha512-B4SznlXwVpaLDa7Tbi6zLuueria2d/PmFDhXyDymPGrk2r1n/RMJmcn5FZq1L64k+Jsyte1lKvOr7lP9Xo80mQ==} + '@next/eslint-plugin-next@16.3.3': + resolution: {integrity: sha512-pbEh30vvjKpDoTAmo1v3q2uM4JUi8QaEBpbmjWvGfoec2jLghy/WNtvzAT0bk+Ik9oz6etjt4YjXEk4BQnicCw==} - '@next/swc-darwin-arm64@16.3.1': - resolution: {integrity: sha512-ABMIu2zQ7cnNIHm5ivKGwZwUrm0pAai3yiJ/gK/rF1c1VP9UOnj7XECbMKFdVKp9I9eMYq9NoDs1WXOoowxzJw==} + '@next/swc-darwin-arm64@16.3.3': + resolution: {integrity: sha512-8Hiv32QJPwdV6KYJ8meR9SBA061tQqnIKTJDocvOXlEQqib0xMFpzArosuffFUUc0sslbh7QQ8a3Yey1QV8EIw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@16.3.1': - resolution: {integrity: sha512-gNG21e/UnrroeScbY/QndUEdl0mF1FRibW7BBeYUz/5ABCepjqDdEdgr592vpzMtCn/m7FTjYq3TN4TpyDnutw==} + '@next/swc-darwin-x64@16.3.3': + resolution: {integrity: sha512-A1lgKgwVchRYmSe467zdwhxT9040dd8lH+o65sL5Jet8fjB4kegw/rDyPIpYVRb6jAqwXFOJpjIXJLxQKLiE3A==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@16.3.1': - resolution: {integrity: sha512-6B6Lw016iwNUQuaJoraMMTLh6TwHzFUtxipSScD1F3YyymcrRWkobodRS2ftIOkF5vrs4zNlyUrTC5YZQ9Lz5w==} + '@next/swc-linux-arm64-gnu@16.3.3': + resolution: {integrity: sha512-bf0FIssMFueU2dm7vQEWWxk0c8UjKTdW0yzuh0sQsD8pf1+KCLDdaqhYZNMYGmXwEOiHAUzgBKudovIlcvvBjg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [glibc] - '@next/swc-linux-arm64-musl@16.3.1': - resolution: {integrity: sha512-JUiPXZKK9wOhjf4MgDiH29GZLxfqOesbLtHq2pDxwH/WwscTRV2ToymnOTh1egzaZf0ueUf8T2+CeYTGHjW0Iw==} + '@next/swc-linux-arm64-musl@16.3.3': + resolution: {integrity: sha512-W7viwCk9JY/cAkdz/A273rd5bb3RgT/IHwR7Upv90tunjBWNtAAhGhoecHh+teRNRSinuAFmE+l7fwZ4YKkrXg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [musl] - '@next/swc-linux-x64-gnu@16.3.1': - resolution: {integrity: sha512-Uog9jsrmIRIL/lfvIp9htmskSNC7JcQsMVucXL2V2YY1y/D9IUN3LPEafqy0zRJ2cIU1SQ0V6F6TlffQ+pLAGg==} + '@next/swc-linux-x64-gnu@16.3.3': + resolution: {integrity: sha512-0W46zw1N3ODpI6n0GeivHvvob1pooozgZVqy65k0mh4/7vr+FbY9+WpHzNVXjHipJf/A3FDheBG19H1s5A25rA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [glibc] - '@next/swc-linux-x64-musl@16.3.1': - resolution: {integrity: sha512-6yy3FT13KgUFOj5H8bl8w/6nKiJwHIvbtwh1V+1acsu+7y4tJjnemSa6mhsh53BeoVrlozE+fMgZhXH46WmjMA==} + '@next/swc-linux-x64-musl@16.3.3': + resolution: {integrity: sha512-H4mBso8ZTMBPtdT0PN0pBx2ayTvQuTuvS6qT13d77yVFJXAPCxkyIhLTmdMaGTJs0krQYI/qpzdHijCeihXhbg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [musl] - '@next/swc-win32-arm64-msvc@16.3.1': - resolution: {integrity: sha512-iOoN1QecUoGNZik536U/vtK43YwgyrCsGIkth52yIkl612n+0C9MjSnJbQAikISpb+WYRooBVhaDlUW7iZoKog==} + '@next/swc-win32-arm64-msvc@16.3.3': + resolution: {integrity: sha512-cTMUJpcEGmeywofCUfhR+rSsoE33+rVPnPEYNTNdLNlsOeEg/vktOsKUSTb28vUGqD2jkm4Zaskcwn7OCI6FQg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@16.3.1': - resolution: {integrity: sha512-d/k+PpAriUPaeMJJOG7HUSdqfEX46FEPWU1p3/nm2ACmXhj9hFEWdFODUBIpkuijXYkfL90qZzTqVPRp4BW/hw==} + '@next/swc-win32-x64-msvc@16.3.3': + resolution: {integrity: sha512-2VR4cTBzHXaBjnGsuH6GyJjENzQOmHeAh11uY1iUhjm3j5dEUrVJuUj+VL78jaGi/Dik8xS76zEj18BsFhlVZQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1287,21 +1287,21 @@ packages: '@tailwindcss/postcss@4.3.3': resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==} - '@tiptap/core@3.30.4': - resolution: {integrity: sha512-V9yKuUfV8qC9WBrnVxkFWmYLBomc3d1CwXoFSjED5DRu5q2oyxv07F+jOJSRogJAY+feHjuxvjhixwxeHm2DXQ==} + '@tiptap/core@3.31.3': + resolution: {integrity: sha512-Cz50pvciQrxdSxgTkHOVz0uD0Yl/8Xt0QatGD6ILm47jW8EzyHR9RkUGs/D5IqzXKuVPntfw1ttaT926vXfiRg==} peerDependencies: - '@tiptap/pm': 3.30.4 + '@tiptap/pm': 3.31.3 - '@tiptap/extension-blockquote@3.30.4': - resolution: {integrity: sha512-n25/pFfDpZRJS4f6Ga/PkNrQFBEr3pRvPkDlY99kl8Kt8jFa1EUxbx+uUVIilqwiUjUnHtwCfqjSDFooQjezjg==} + '@tiptap/extension-blockquote@3.31.3': + resolution: {integrity: sha512-fyY2XMbyDDDfOTQ1Qdrnqa1qwC9DWE4n7AfE0EKQI0G8MfLV8RaDlLDcOZDJ9JbMPY7/Gx7EjyK4NKxSW9n2hQ==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/pm': 3.31.3 - '@tiptap/extension-bold@3.30.4': - resolution: {integrity: sha512-eCOkf+/jdQte7lTZ4pQF10akrsFM4TzYc0ysSAkPa7QA+ex1aI8QT5UUx+mK8RwFo57lqE8PCX/Mx1gTqlCDnQ==} + '@tiptap/extension-bold@3.31.3': + resolution: {integrity: sha512-dIuYhKk8TitKU/FeDpoTeWZhU42YgDN5npgWNjAmMmRktPdoxnH3/wGSiwXlqZgJWjehN7kPWDePWpJeAImGpQ==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 '@tiptap/extension-bubble-menu@3.31.3': resolution: {integrity: sha512-EV6ZnwKc++2OM/OcD54n8s1B7C9LP7GKAtdEPwu0t3BYJf3sG8Ueoinf7SgGPO9oMPg96GneOkDNm1urMV167g==} @@ -1309,47 +1309,47 @@ packages: '@tiptap/core': 3.31.3 '@tiptap/pm': 3.31.3 - '@tiptap/extension-bullet-list@3.30.4': - resolution: {integrity: sha512-kJFOF3U4b1ad4T7Vm+CIIp+nxcr6wwWVeqpVe6Jhq9gudsWCKP0+KVAmOiJCePoDu9fpc/ZuGMXDefXYnyQDxg==} + '@tiptap/extension-bullet-list@3.31.3': + resolution: {integrity: sha512-qEyyoPapPef4LO8XKaN83bxtaNzkJ4kFn/IxLnEKd4BJ3Mvi4MH2yJYlyDqwFnMoev4pMA1zBHRAt/C0THRmZw==} peerDependencies: - '@tiptap/extension-list': 3.30.4 + '@tiptap/extension-list': 3.31.3 - '@tiptap/extension-code-block-lowlight@3.30.4': - resolution: {integrity: sha512-oXZdrUWp530PT3q5E/ZewigjelHvExMDEyS+HusNF/rUXnmBugt4RszkA3lO38VYNoa/8FiOdRW+/yx1SYXlxw==} + '@tiptap/extension-code-block-lowlight@3.31.3': + resolution: {integrity: sha512-DN21CYEL4bm01vyB/wiyDPKrpiyalI5okTWx90jRuTqRzbnkPlnng1Vdo9L220w3GXct5Exe6iI01E7F19bC5A==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/extension-code-block': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/extension-code-block': 3.31.3 + '@tiptap/pm': 3.31.3 highlight.js: ^11 lowlight: ^2 || ^3 - '@tiptap/extension-code-block@3.30.4': - resolution: {integrity: sha512-eKLKxgLCvi+M5tiLkW+fIMzDtR7HvSKnigSE9RYHZmzSrv1ejVjgNj5FH8nGTim98hXiQGfWotss3zqG6bpdDw==} + '@tiptap/extension-code-block@3.31.3': + resolution: {integrity: sha512-nvknt4FhyJQjYcvxptmeUlFsIAc8ibua3E5BN4Pim374/9RWepH4cdE9X0/qUTtguHElLx0iKtSIY3rW2qGTFA==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/pm': 3.31.3 - '@tiptap/extension-code@3.30.4': - resolution: {integrity: sha512-z9v9rBA/0MecUvf8QkcKKOGgceO9X3DT/JvFNka8Mdd68V5fhBs0jGsxYrj3qDWtdXyyUQIWs0t8HzL6LTdLiA==} + '@tiptap/extension-code@3.31.3': + resolution: {integrity: sha512-SzxOqchrD2AcN3uT67PjKmRFEMOU3vNNiwNaamZJUbZrI6Hmy+bvdHJrc3jrIddyyCrAtsnAfRI0cmorW1jGfg==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-details@3.30.4': - resolution: {integrity: sha512-a+UJjPxr77zVI1oCzDO/9lRkTdIg830oO+otMTOnM6xCmLIpxktDikCkYP1kJyU5GO6Fwp26J39MGKWUNIizXA==} + '@tiptap/extension-details@3.31.3': + resolution: {integrity: sha512-J5kdZy31wb97iKUR4sDsX0sEyRPlTijKKRAnVbInY2aNdFuNBTBdMPmblEJztxfMN+TmDrU2kCVv72J9B1SrJg==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/extension-text-style': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/extension-text-style': 3.31.3 + '@tiptap/pm': 3.31.3 - '@tiptap/extension-document@3.30.4': - resolution: {integrity: sha512-N+FbI+X1FVH8HxsM8C4fNkkzKXiyhXc9oh9oSqAIKOAAYGAjnHLMxW9TzYXbvm60SlAn6DIMypNf6nULGEc1oQ==} + '@tiptap/extension-document@3.31.3': + resolution: {integrity: sha512-EexgmqnyDNyGlISxo7SMrp5MygpJYmqD+0cY5jB6L1U6L4CpKKRWUt8OO1sWzEHDE1+TTvwt+WIFoIWAziOtEA==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-dropcursor@3.30.4': - resolution: {integrity: sha512-P1V0y/FKdyNVBImeW3WN+uGI77Uboc0dW44izAjrII0jcW2KUoBQeNrbbm9UZR1xuRvQJ1Z0OrFHmYrxP5ClNQ==} + '@tiptap/extension-dropcursor@3.31.3': + resolution: {integrity: sha512-NWomSfu5CSC7VacnMSDzKT8qm66SzMfZwVPEtwY5bPpRTJgTiT1rNK0neDrrzfMN27MfylGyKWWf7Q5Qf8w/fg==} peerDependencies: - '@tiptap/extensions': 3.30.4 + '@tiptap/extensions': 3.31.3 '@tiptap/extension-floating-menu@3.31.3': resolution: {integrity: sha512-rd4VJ9PGSP9Eop8ZTEwaLZcMzMXLuJKe3hUNf58rq+zANpwM+9fI+vB7g9MAc3eXwUNDxNDVACFIL2oeBqpQ3A==} @@ -1358,158 +1358,158 @@ packages: '@tiptap/core': 3.31.3 '@tiptap/pm': 3.31.3 - '@tiptap/extension-gapcursor@3.30.4': - resolution: {integrity: sha512-wsuXsB8Rp9BgfWlWYsRVzoHg9LwhoPAQGaw/gku1buDSTMcbLYQvok5MwJ/uJRECaJRLGgbUe5WBXoRvSY+o3g==} + '@tiptap/extension-gapcursor@3.31.3': + resolution: {integrity: sha512-EBXKb1FrVStsNYCcRGtd9jmzveCvR+eqgg1rVqoONrqFK6U7bga6LN+1dMKroP1kliDVgveYkP3vRYxqw+rFqg==} peerDependencies: - '@tiptap/extensions': 3.30.4 + '@tiptap/extensions': 3.31.3 - '@tiptap/extension-hard-break@3.30.4': - resolution: {integrity: sha512-eZ66SyfgmMK861S5SYtQROT/+ZfXtDHxllz7ao+X+dcl+DMdffmOzBeSfwrHQENmgl7umjbdAjqC7PT95jaU+w==} + '@tiptap/extension-hard-break@3.31.3': + resolution: {integrity: sha512-QAdCvNO4+yW9ATwsrej11NTkDYFqPLIEQr3ARNrKOK1qaiS7A0fia2SEukb/hrkP3A6mbozhoQt2r2RGUf/DpQ==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-heading@3.30.4': - resolution: {integrity: sha512-sVJxoRnbfK/QC7IoUw/Ezzx9b87+cqFz5d5WZvN8O8yobDWuh7IS8ZgqZiPypTW5RuhnZI+ahvmSyO3WLm8q5Q==} + '@tiptap/extension-heading@3.31.3': + resolution: {integrity: sha512-rk5VHMAeQcg06SLauN6EGdD2jc0O2qY8QkZYPd0LxNvLblw2BxBx+lxUQSYwLAT9Ie5914gKIK2YbRyO2Ts3ig==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-highlight@3.30.4': - resolution: {integrity: sha512-4EsZeEWB8NAZOLE1gSUFJQgF9sgaCRbGb47Posnjq4I2DMYuZGnyl2n0c0v/R06LV5ahz4IZvSZ4JskkSFsvIQ==} + '@tiptap/extension-highlight@3.31.3': + resolution: {integrity: sha512-97m1nDzTAjJaJZWe5hVOBMC2rjBZvEwTXA39zhjnaE/snb8Cy4H9A3+/sw9HQJBXMoG7tdOPG9kUlM3weYtLcQ==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-horizontal-rule@3.30.4': - resolution: {integrity: sha512-RmvjVVkUf5pF70XvwI7Sb4vIUSDbLTLEcFl1l5X9vPcDgDT5G0SiUL6l8F49+qYc6wrMvnLcenApnAiiQ0Vbpw==} + '@tiptap/extension-horizontal-rule@3.31.3': + resolution: {integrity: sha512-YnHGy2KShRwvCseAmmxl9VP7R0qaj8QMp3DA6DJWZqp7r5gLGvDkAqhedxqqefqsE4Y43hjkBdjtB9Ce78LkIw==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/pm': 3.31.3 - '@tiptap/extension-image@3.30.4': - resolution: {integrity: sha512-BwO+SJ+1ZWFLDFbebT80q0PlsbrnmWRExzQqurubM93M22SlADnQxNzS7AKfNmv/e3qKAAXXsoBOkx66BuFjaQ==} + '@tiptap/extension-image@3.31.3': + resolution: {integrity: sha512-wWNG9BOtx2Cg4vwxPVGDIJ5DGX+ETkldeoaFJLB1NXUL4OPUiVTf8cHZ+hdYgJWP704BEB7jQgjlpvdi6VigTg==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-italic@3.30.4': - resolution: {integrity: sha512-6cEjcyjPRcLEMB75BwiUc6S7yzkqc7VPXCeRgY26UqMg4AvcLrseY70+pO4sLv3n2DS5w8DBbMXZJ4rb1BhpUw==} + '@tiptap/extension-italic@3.31.3': + resolution: {integrity: sha512-ibGvdvAPyfxBMUVNRI43eb9h2/Jka1MRG5GtnGqbcCX/2+Y/y0EOfFrPQPkuYphiWQYyu9+FzPKMB/pjuaLuKQ==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-link@3.30.4': - resolution: {integrity: sha512-HPHaey3+nQZl+lsr/RvjoXSgSC67SAkNEF4qNELzzDwMUfI0UrZ3H/HhBe6XBeRnGli9gfuSpeRkh63ke5JpOw==} + '@tiptap/extension-link@3.31.3': + resolution: {integrity: sha512-986wOQzTL9Zr5lf84LCLpm+YOms8A0K39/8DVoqRfebqcOe0/eq4bnztmAlfabOd+kJY92g3AgZERFUx/w+dcw==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/pm': 3.31.3 - '@tiptap/extension-list-item@3.30.4': - resolution: {integrity: sha512-8E1ffdC7v3dwSrsqyxY3YP5uEQHTrwBDDmYF6o2YoHfzQ9nhXX5GmBz8fTxukjXUzSpuO76N/gwHIM8hBfdxMQ==} + '@tiptap/extension-list-item@3.31.3': + resolution: {integrity: sha512-4QlKOriJJMvg95QJTEsy9BUYPBQ6UvJyb8WURRwdUtQUkkqb8h32lg/eyQUv2FzW9IT1AdUyNZfVaxH64kRfQA==} peerDependencies: - '@tiptap/extension-list': 3.30.4 + '@tiptap/extension-list': 3.31.3 - '@tiptap/extension-list-keymap@3.30.4': - resolution: {integrity: sha512-6RIzF3aThqIt4sia81K+6wA7H7bgPKjd3D66qLOGxdqdyfnAegk0OD5pUYhMZKhDCWGYKylyRVd2yIn/VNXqAg==} + '@tiptap/extension-list-keymap@3.31.3': + resolution: {integrity: sha512-If8UOEdDZbPJU6iYTvLtH6DOp2KBy6BKxg9UELL1AevVetGHEF/7lW8hP50Gn1tHMVpPRqmhSzVrJRpEJJgb/Q==} peerDependencies: - '@tiptap/extension-list': 3.30.4 + '@tiptap/extension-list': 3.31.3 - '@tiptap/extension-list@3.30.4': - resolution: {integrity: sha512-Usqez9DBRoG78tdLwPDcd1j1mBBU7mr5D2yrRP2JL/eXXkhAfdWqEFRYXwct5T4/o9JkGcW3aQf+gUvp12v0pw==} + '@tiptap/extension-list@3.31.3': + resolution: {integrity: sha512-LoveGnC0FVdCV4jUNBaG1ZA+KWE07+adzV3kGy6uUYFcJEjbVUHTnPDrBOob3IwOSO3sCwIkvQb6EVYeXn/4yg==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/pm': 3.31.3 - '@tiptap/extension-ordered-list@3.30.4': - resolution: {integrity: sha512-hInlH8I2UFGGULm9XLPtLWWFBECrYf/eNkloQb+udbF7ltLBL5JRCPcB3aM29qSSUQVxCCN8ICHdbwgpnTUAsw==} + '@tiptap/extension-ordered-list@3.31.3': + resolution: {integrity: sha512-mp3g11NgA/PYu8rj7J7Ez3l4qBy6WfTSmHIG4PZvEGG5w2oUAIkgb9DU7nPPzjmeme27oazFYZw+AtZA0+u4tw==} peerDependencies: - '@tiptap/extension-list': 3.30.4 + '@tiptap/extension-list': 3.31.3 - '@tiptap/extension-paragraph@3.30.4': - resolution: {integrity: sha512-gM0WXvOP1tNcvpyRXTCtGhwVxye0VaFMCzDPjLrVAUtZMpo3cOrqDSrFl5tCurA59Qc2p5TUOR4g3/fKw8Yx9Q==} + '@tiptap/extension-paragraph@3.31.3': + resolution: {integrity: sha512-+iPku7wJfy5hbNDNLX8dveFtYVsZMmh7vztjuq8hT3mipSC4IByDehDbU8fzUCjfXiEzmI7mQn7c8LGmHULuzA==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-placeholder@3.30.4': - resolution: {integrity: sha512-Bbwzse6oTNwkQVmBQF45YJ/zpFQut52tT+s+u6cWi/SwyYTMeaU4XNOV6KidkM8urERFCkF/PplAevusvWuowA==} + '@tiptap/extension-placeholder@3.31.3': + resolution: {integrity: sha512-9jYtR8ELEw7GVaruyrm4oFkPcjig9Q+crc+dpmarhBNXUmxagCdlhVzNwCJ2WJRzvBAtx59sEYqNTU38Wx8S3A==} peerDependencies: - '@tiptap/extensions': 3.30.4 + '@tiptap/extensions': 3.31.3 - '@tiptap/extension-strike@3.30.4': - resolution: {integrity: sha512-iM3QhkEvNwDsxyNKTZM4wwqYhIKOjgXHTamPWnCICrPQ3aYFVdidfpDMePlHl6XL8aEAqPa1Xlj0aumFvSphOQ==} + '@tiptap/extension-strike@3.31.3': + resolution: {integrity: sha512-G29bhKttYwcKHT+BI6emWVFol3RO/gUXxQVcmr/iT8LXXy7j8J6HFUnsKM+Kg5YlP1rxMRgsa65dbrQVahZi0A==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-table-cell@3.30.4': - resolution: {integrity: sha512-/jlC9ucT7C0D0mzFRksfx4lx6lpWXc7OpAZv9Ml+Bitex6ghyW2ownxDzIfaAVBNv2KZY3uOpsQ2lOBItjehJg==} + '@tiptap/extension-table-cell@3.31.3': + resolution: {integrity: sha512-5nueKR/p/IX6B4etWqHjyRsjNfDf6dJZaRgfw1/1l90CJe2h3tTZk4JbUKWN3Mo4FzZuYKzmU3fxcZ8pSVOeJQ==} peerDependencies: - '@tiptap/extension-table': 3.30.4 + '@tiptap/extension-table': 3.31.3 - '@tiptap/extension-table-header@3.30.4': - resolution: {integrity: sha512-9Uk/R0tOUKVDKZUmAZncxT93SwzfsJvHFfutd8qZNB4+Mg74sSSN3vVjcfCPAUqqVrxV8hXdoN8+3MqP2INPFQ==} + '@tiptap/extension-table-header@3.31.3': + resolution: {integrity: sha512-sstVtNQiBYX4P16vlhwBYPsthxDnodHWQfGq0EUQM40Z7H796Lgh9t1qYtu8yARQuHKzvINRwJCSy6DZ8YTDtQ==} peerDependencies: - '@tiptap/extension-table': 3.30.4 + '@tiptap/extension-table': 3.31.3 - '@tiptap/extension-table-row@3.30.4': - resolution: {integrity: sha512-IiUvR73B7vU0WJW+zVAr7VRCtt9pHZW/v67QNAD0EZ52fJLA6UV/TzZbX58JqTRUtpdpGLkdiOLMVgZTP9rUrQ==} + '@tiptap/extension-table-row@3.31.3': + resolution: {integrity: sha512-up6tDK+hYVTFDeJ3XqKO0WJqBzyXNfGxMoimo5h83jrq9dcNh0oPCOzglZ7rdo8GH9I3VJ2fNKxxU2Eg2HcMoQ==} peerDependencies: - '@tiptap/extension-table': 3.30.4 + '@tiptap/extension-table': 3.31.3 - '@tiptap/extension-table@3.30.4': - resolution: {integrity: sha512-hH6E4y4QK8F2h4Eb/qiu8/tRXSQPbJn8pNOIQqcvA30luUnFWSpqHFDxO/a/XrzwF6F1l268WTekrn0PKogOzg==} + '@tiptap/extension-table@3.31.3': + resolution: {integrity: sha512-7cnVPHhdiGGeauYqca6JVyPLTqZbqFEEk9nn2e2E8+fBo6zVtV07AktJBqth/XEzjZxcUmGxjoeuWYAisWjUHg==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/pm': 3.31.3 - '@tiptap/extension-task-item@3.30.4': - resolution: {integrity: sha512-PArRkxRkajtqkCV7wICVCkh6LBtQhvMqRgPmoEfdOIwGSnaWXCmAe8AmtLmCjhtHRxZ5aJlYH2C0/vm2ocoYxg==} + '@tiptap/extension-task-item@3.31.3': + resolution: {integrity: sha512-gCWvvXsCzi9tVFXPqKlkbU81XxtIdfjGy7FM9QFRKiWAvq5uv+Q5nvwrCyMVyP4bA7zRGWFaPzwjL68djgzoBw==} peerDependencies: - '@tiptap/extension-list': 3.30.4 + '@tiptap/extension-list': 3.31.3 - '@tiptap/extension-task-list@3.30.4': - resolution: {integrity: sha512-X83/OuCBnY97rEusL+1figMUv+aaJiSJuSKdOjm3zJi3M1KI0GbyBVZ3/LL5Y2hynfeu1rOEVd/fkaP3Z/HUBw==} + '@tiptap/extension-task-list@3.31.3': + resolution: {integrity: sha512-3WgVzmfEnDbmxbjUBlvTiKpT53KSBnnYhXUVQxM0nz1vpoWG8QifhsnCVsNI6TZmhgR0x/jY+UW9Hc/WLF8DkQ==} peerDependencies: - '@tiptap/extension-list': 3.30.4 + '@tiptap/extension-list': 3.31.3 - '@tiptap/extension-text-style@3.30.4': - resolution: {integrity: sha512-BNd+qnXHVHBk7qAGyXpa2U4mvSNZKmc0vP0uH6V8+OQBw6Kl9WzTWv+V2qX+yjXFs/A2Bl/XVTdWaHctGxW/hg==} + '@tiptap/extension-text-style@3.31.3': + resolution: {integrity: sha512-wgjWWrjZwRZHiaDTQPX2am1y/4ePgRgGWF/2MOfSb7g4d5229p4aVtbT1JT7wu9z8OC482pEqcTlhdvgftvW7A==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-text@3.30.4': - resolution: {integrity: sha512-bzgVlPhkVan+m6jycXkyq08fKCNyQff/cl/5U+/wQf8s3GlX+Le2/pTxbbC3ClfO1D8VLzLwcd2HJTYIoBOdAA==} + '@tiptap/extension-text@3.31.3': + resolution: {integrity: sha512-gdsWtF+taeaCu6V+5Ct10fGo0ACUy1GnYtbb+mcathBt8OqbT+Ws60p/yEmKesBDz2Hn+B5IcWy6+2BBZl5ZTg==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extension-underline@3.30.4': - resolution: {integrity: sha512-h6nM3ykKswJLWvJVD1eiUFbanNmNj2SeV+2vuW666/xOy2WPyMnE2NZnsbvCKeK0wlUj7AE3l1m602mFwA4sDg==} + '@tiptap/extension-underline@3.31.3': + resolution: {integrity: sha512-HghdJaOwRqYzsAxqSyNyb+IWyOMcdCl8IoiBETA9BZCJAqdXzFLcuWp7CqCqJPam9dgkWosSoHqTCAO4nTBfpw==} peerDependencies: - '@tiptap/core': 3.30.4 + '@tiptap/core': 3.31.3 - '@tiptap/extensions@3.30.4': - resolution: {integrity: sha512-WeBl/ggeNCOoOySX7647lwtSUHWbCh8I1Qqp8NQBsGyHXEE6/7jHbKcxpw4fplOgScgVMfPz8WZ+3yrfXYCUFw==} + '@tiptap/extensions@3.31.3': + resolution: {integrity: sha512-8sJNPGGUe8f3aDojcOW5cfVL7I5NrBbE0UWxG08qoi9Tea6qWbvQJsCR9tsrOapr/DaLr3kpbGZ9s1gEEfcNcA==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/pm': 3.31.3 - '@tiptap/pm@3.30.4': - resolution: {integrity: sha512-oPbE+BOzzDKkxsvF9wepTWELvq385oifDkKIigqKCPKpGqplEIHIjNztCj/nOqHCfJBiU9LcoyyWH0qkHAQ9TQ==} + '@tiptap/pm@3.31.3': + resolution: {integrity: sha512-sZime0SWsz/k62W2WvHx5Ig7G2h7kVhrrmnqy+wEgIHfDwEfOlelRjaWCiBCFlF7dxGUntJusCh9FxlLhni0Ag==} - '@tiptap/react@3.30.4': - resolution: {integrity: sha512-NxGcKg4xBF6ngk6xORyzRCvG9zb7Z/cf59GpDBsiYpPpD/6m+J4kfNF0KVIOhRSAhNxm2u2ZPuGIWBtS/CDUBQ==} + '@tiptap/react@3.31.3': + resolution: {integrity: sha512-QiwQqvaLFLm5EMFu5tg7nAgXJxCUiUTLD8EsK+TqVV5P4bqOoMOCM39khbhXTJyahCuYpiFWx5YOSDtC/JiPtg==} peerDependencies: - '@tiptap/core': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/pm': 3.31.3 '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 '@types/react-dom': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tiptap/starter-kit@3.30.4': - resolution: {integrity: sha512-rZiv2QOqfQU4/MNsAmvbymIwx0tKrGrtdJg76aEaej+aGU1QNDhZbUNutV8AnZxFjSJMm8rt810qzAU98OmCAg==} + '@tiptap/starter-kit@3.31.3': + resolution: {integrity: sha512-WKof9RewdmGHvWJ1wn0/HVNG2mV+HOgVRyJkKekuM9fgr6BZAAH/xZsWE1eon+94JnQ+KtK2ThydXQM/qc6b2A==} - '@tiptap/suggestion@3.30.4': - resolution: {integrity: sha512-viJYyd8xyYFlJmvxPphj/gojMwDIT1g2HRWEzKstbcLb1ox8X+Ijy45PlqgCJFIIxO9RicfIxdaR/hMK2tqG2Q==} + '@tiptap/suggestion@3.31.3': + resolution: {integrity: sha512-z1OQ/Yx6seMZehi1AcmNkyJ8qkHQzybArmCyRdmreS4YL9C4bPMBe5lbMfFsArYs+KD5JyHwps5j7J/YE5BIuw==} peerDependencies: '@floating-ui/dom': ^1.0.0 - '@tiptap/core': 3.30.4 - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3 + '@tiptap/pm': 3.31.3 '@tybys/wasm-util@0.10.3': resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} @@ -2313,8 +2313,8 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - eslint-config-next@16.3.1: - resolution: {integrity: sha512-0vtrpwFVHFEkycUgV/DyrG29OS+HSRdah5Yu8YuZoiBMtlAT6NIiWzaLwDkJZxr2kGfx+9LIvfQ7KHAlEs0VsA==} + eslint-config-next@16.3.3: + resolution: {integrity: sha512-teqtsR26tnlfXFHfVLTM/4tzEzU8DMu6GS1sddZzhfGzgd2f2ofbgDUcsk6cssSCzX6Tk6fmWifJcdANSdPJrw==} peerDependencies: eslint: '>=9.0.0' typescript: '>=3.3.1' @@ -2634,14 +2634,14 @@ packages: hono-rate-limiter@0.5.3: resolution: {integrity: sha512-M0DxbVMpPELEzLi0AJg1XyBHLGJXz7GySjsPoK+gc5YeeBsdGDGe+2RvVuCAv8ydINiwlbxqYMNxUEyYfRji/A==} peerDependencies: - hono: ^4.12.34 + hono: ^4.13.5 unstorage: ^1.17.3 peerDependenciesMeta: unstorage: optional: true - hono@4.13.2: - resolution: {integrity: sha512-JydRilDRkYBQMt9qR9U92mXxmbGqsqSn/IKOrh4e7/gEbn+0zSr8igTu0obwJoNGN4sez28DIql7FBHWydoJpA==} + hono@4.13.7: + resolution: {integrity: sha512-c8/gF9ac8Y78/agExVocyLevgR+JlpNB444Py0FSX8pJoPdYUfUzRcXtYEYGwt6l19qIlVZPN5Mfsw9jFShmQQ==} engines: {node: '>=16.9.0'} html-url-attributes@3.0.1: @@ -2827,8 +2827,8 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.3.1: - resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==} + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} hasBin: true jsesc@3.1.0: @@ -3197,8 +3197,8 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} - next@16.3.1: - resolution: {integrity: sha512-hsAp0i7Rh+/dhe7DGIeN2YlpLM1DP4MNxti9EtDMtqcO612X81MvvEj388/oTce9U1EcEIOWDlGq0zRwrBKvuA==} + next@16.3.3: + resolution: {integrity: sha512-tuRTx1nQ/yVw83cwJBo9F+njGUgMn3UHQycreWHB8XsStvvAh1AthbI8/4IpKnFaF58F+iSiHejYOlMQ/eq83g==} engines: {node: '>=20.9.0'} hasBin: true peerDependencies: @@ -3596,8 +3596,8 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} - sharp@0.35.3: - resolution: {integrity: sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==} + sharp@0.35.4: + resolution: {integrity: sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==} engines: {node: '>=20.9.0'} peerDependencies: '@types/node': '*' @@ -4331,7 +4331,7 @@ snapshots: globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.3.1 + js-yaml: 4.3.2 minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -4357,9 +4357,9 @@ snapshots: '@floating-ui/utils@0.2.12': {} - '@hono/node-server@2.1.1(hono@4.13.2)': + '@hono/node-server@2.1.1(hono@4.13.7)': dependencies: - hono: 4.13.2 + hono: 4.13.7 '@humanfs/core@0.19.2': dependencies: @@ -4380,108 +4380,108 @@ snapshots: '@img/colour@1.1.0': optional: true - '@img/sharp-darwin-arm64@0.35.3': + '@img/sharp-darwin-arm64@0.35.4': optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.3.2 + '@img/sharp-libvips-darwin-arm64': 1.3.3 optional: true - '@img/sharp-darwin-x64@0.35.3': + '@img/sharp-darwin-x64@0.35.4': optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.3.2 + '@img/sharp-libvips-darwin-x64': 1.3.3 optional: true - '@img/sharp-freebsd-wasm32@0.35.3': + '@img/sharp-freebsd-wasm32@0.35.4': dependencies: - '@img/sharp-wasm32': 0.35.3 + '@img/sharp-wasm32': 0.35.4 optional: true - '@img/sharp-libvips-darwin-arm64@1.3.2': + '@img/sharp-libvips-darwin-arm64@1.3.3': optional: true - '@img/sharp-libvips-darwin-x64@1.3.2': + '@img/sharp-libvips-darwin-x64@1.3.3': optional: true - '@img/sharp-libvips-linux-arm64@1.3.2': + '@img/sharp-libvips-linux-arm64@1.3.3': optional: true - '@img/sharp-libvips-linux-arm@1.3.2': + '@img/sharp-libvips-linux-arm@1.3.3': optional: true - '@img/sharp-libvips-linux-ppc64@1.3.2': + '@img/sharp-libvips-linux-ppc64@1.3.3': optional: true - '@img/sharp-libvips-linux-riscv64@1.3.2': + '@img/sharp-libvips-linux-riscv64@1.3.3': optional: true - '@img/sharp-libvips-linux-s390x@1.3.2': + '@img/sharp-libvips-linux-s390x@1.3.3': optional: true - '@img/sharp-libvips-linux-x64@1.3.2': + '@img/sharp-libvips-linux-x64@1.3.3': optional: true - '@img/sharp-libvips-linuxmusl-arm64@1.3.2': + '@img/sharp-libvips-linuxmusl-arm64@1.3.3': optional: true - '@img/sharp-libvips-linuxmusl-x64@1.3.2': + '@img/sharp-libvips-linuxmusl-x64@1.3.3': optional: true - '@img/sharp-linux-arm64@0.35.3': + '@img/sharp-linux-arm64@0.35.4': optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.3.2 + '@img/sharp-libvips-linux-arm64': 1.3.3 optional: true - '@img/sharp-linux-arm@0.35.3': + '@img/sharp-linux-arm@0.35.4': optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.3.2 + '@img/sharp-libvips-linux-arm': 1.3.3 optional: true - '@img/sharp-linux-ppc64@0.35.3': + '@img/sharp-linux-ppc64@0.35.4': optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.3.2 + '@img/sharp-libvips-linux-ppc64': 1.3.3 optional: true - '@img/sharp-linux-riscv64@0.35.3': + '@img/sharp-linux-riscv64@0.35.4': optionalDependencies: - '@img/sharp-libvips-linux-riscv64': 1.3.2 + '@img/sharp-libvips-linux-riscv64': 1.3.3 optional: true - '@img/sharp-linux-s390x@0.35.3': + '@img/sharp-linux-s390x@0.35.4': optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.3.2 + '@img/sharp-libvips-linux-s390x': 1.3.3 optional: true - '@img/sharp-linux-x64@0.35.3': + '@img/sharp-linux-x64@0.35.4': optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.3.2 + '@img/sharp-libvips-linux-x64': 1.3.3 optional: true - '@img/sharp-linuxmusl-arm64@0.35.3': + '@img/sharp-linuxmusl-arm64@0.35.4': optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.3.2 + '@img/sharp-libvips-linuxmusl-arm64': 1.3.3 optional: true - '@img/sharp-linuxmusl-x64@0.35.3': + '@img/sharp-linuxmusl-x64@0.35.4': optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.3.2 + '@img/sharp-libvips-linuxmusl-x64': 1.3.3 optional: true - '@img/sharp-wasm32@0.35.3': + '@img/sharp-wasm32@0.35.4': dependencies: '@emnapi/runtime': 1.11.3 optional: true - '@img/sharp-webcontainers-wasm32@0.35.3': + '@img/sharp-webcontainers-wasm32@0.35.4': dependencies: - '@img/sharp-wasm32': 0.35.3 + '@img/sharp-wasm32': 0.35.4 optional: true - '@img/sharp-win32-arm64@0.35.3': + '@img/sharp-win32-arm64@0.35.4': optional: true - '@img/sharp-win32-ia32@0.35.3': + '@img/sharp-win32-ia32@0.35.4': optional: true - '@img/sharp-win32-x64@0.35.3': + '@img/sharp-win32-x64@0.35.4': optional: true '@jridgewell/gen-mapping@0.3.13': @@ -4528,37 +4528,37 @@ snapshots: '@neondatabase/serverless@1.1.0': {} - '@next/env@16.3.1': {} + '@next/env@16.3.3': {} - '@next/eslint-plugin-next@16.3.1(eslint@9.39.5(jiti@2.7.0))': + '@next/eslint-plugin-next@16.3.3(eslint@9.39.5(jiti@2.7.0))': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.5(jiti@2.7.0)) fast-glob: 3.3.1 transitivePeerDependencies: - eslint - '@next/swc-darwin-arm64@16.3.1': + '@next/swc-darwin-arm64@16.3.3': optional: true - '@next/swc-darwin-x64@16.3.1': + '@next/swc-darwin-x64@16.3.3': optional: true - '@next/swc-linux-arm64-gnu@16.3.1': + '@next/swc-linux-arm64-gnu@16.3.3': optional: true - '@next/swc-linux-arm64-musl@16.3.1': + '@next/swc-linux-arm64-musl@16.3.3': optional: true - '@next/swc-linux-x64-gnu@16.3.1': + '@next/swc-linux-x64-gnu@16.3.3': optional: true - '@next/swc-linux-x64-musl@16.3.1': + '@next/swc-linux-x64-musl@16.3.3': optional: true - '@next/swc-win32-arm64-msvc@16.3.1': + '@next/swc-win32-arm64-msvc@16.3.3': optional: true - '@next/swc-win32-x64-msvc@16.3.1': + '@next/swc-win32-x64-msvc@16.3.3': optional: true '@nodelib/fs.scandir@2.1.5': @@ -4656,175 +4656,175 @@ snapshots: postcss: 8.5.26 tailwindcss: 4.3.3 - '@tiptap/core@3.30.4(@tiptap/pm@3.30.4)': + '@tiptap/core@3.31.3(@tiptap/pm@3.31.3)': dependencies: - '@tiptap/pm': 3.30.4 + '@tiptap/pm': 3.31.3 - '@tiptap/extension-blockquote@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/extension-blockquote@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 - '@tiptap/extension-bold@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-bold@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-bubble-menu@3.31.3(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/extension-bubble-menu@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: '@floating-ui/dom': 1.8.0 - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 optional: true - '@tiptap/extension-bullet-list@3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-bullet-list@3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extension-list': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-list': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-code-block-lowlight@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/extension-code-block@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)(highlight.js@11.11.1)(lowlight@3.3.0)': + '@tiptap/extension-code-block-lowlight@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/extension-code-block@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)(highlight.js@11.11.1)(lowlight@3.3.0)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/extension-code-block': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/extension-code-block': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 highlight.js: 11.11.1 lowlight: 3.3.0 - '@tiptap/extension-code-block@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/extension-code-block@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 - '@tiptap/extension-code@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-code@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-details@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/extension-text-style@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)))(@tiptap/pm@3.30.4)': + '@tiptap/extension-details@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/extension-text-style@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)))(@tiptap/pm@3.31.3)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/extension-text-style': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/extension-text-style': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/pm': 3.31.3 - '@tiptap/extension-document@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-document@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-dropcursor@3.30.4(@tiptap/extensions@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-dropcursor@3.31.3(@tiptap/extensions@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extensions': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extensions': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-floating-menu@3.31.3(@floating-ui/dom@1.8.0)(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/extension-floating-menu@3.31.3(@floating-ui/dom@1.8.0)(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: '@floating-ui/dom': 1.8.0 - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 optional: true - '@tiptap/extension-gapcursor@3.30.4(@tiptap/extensions@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-gapcursor@3.31.3(@tiptap/extensions@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extensions': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extensions': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-hard-break@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-hard-break@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-heading@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-heading@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-highlight@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-highlight@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-horizontal-rule@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/extension-horizontal-rule@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 - '@tiptap/extension-image@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-image@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-italic@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-italic@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-link@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/extension-link@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 linkifyjs: 4.3.3 - '@tiptap/extension-list-item@3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-list-item@3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extension-list': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-list': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-list-keymap@3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-list-keymap@3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extension-list': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-list': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 - '@tiptap/extension-ordered-list@3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-ordered-list@3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extension-list': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-list': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-paragraph@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-paragraph@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-placeholder@3.30.4(@tiptap/extensions@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-placeholder@3.31.3(@tiptap/extensions@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extensions': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extensions': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-strike@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-strike@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-table-cell@3.30.4(@tiptap/extension-table@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-table-cell@3.31.3(@tiptap/extension-table@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extension-table': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-table': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-table-header@3.30.4(@tiptap/extension-table@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-table-header@3.31.3(@tiptap/extension-table@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extension-table': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-table': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-table-row@3.30.4(@tiptap/extension-table@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-table-row@3.31.3(@tiptap/extension-table@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extension-table': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-table': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-table@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/extension-table@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 - '@tiptap/extension-task-item@3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-task-item@3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extension-list': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-list': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-task-list@3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4))': + '@tiptap/extension-task-list@3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/extension-list': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-list': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) - '@tiptap/extension-text-style@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-text-style@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-text@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-text@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extension-underline@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))': + '@tiptap/extension-underline@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) - '@tiptap/extensions@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/extensions@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 - '@tiptap/pm@3.30.4': + '@tiptap/pm@3.31.3': dependencies: prosemirror-changeset: 2.4.2 prosemirror-commands: 1.7.2 @@ -4840,10 +4840,10 @@ snapshots: prosemirror-transform: 1.12.1 prosemirror-view: 1.42.3 - '@tiptap/react@3.30.4(@floating-ui/dom@1.8.0)(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + '@tiptap/react@3.31.3(@floating-ui/dom@1.8.0)(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 '@types/react': 19.2.18 '@types/react-dom': 19.2.4(@types/react@19.2.18) '@types/use-sync-external-store': 0.0.6 @@ -4852,43 +4852,43 @@ snapshots: react-dom: 19.2.8(react@19.2.8) use-sync-external-store: 1.6.0(react@19.2.8) optionalDependencies: - '@tiptap/extension-bubble-menu': 3.31.3(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) - '@tiptap/extension-floating-menu': 3.31.3(@floating-ui/dom@1.8.0)(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) + '@tiptap/extension-bubble-menu': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) + '@tiptap/extension-floating-menu': 3.31.3(@floating-ui/dom@1.8.0)(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) transitivePeerDependencies: - '@floating-ui/dom' - '@tiptap/starter-kit@3.30.4': - dependencies: - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/extension-blockquote': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) - '@tiptap/extension-bold': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extension-bullet-list': 3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) - '@tiptap/extension-code': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extension-code-block': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) - '@tiptap/extension-document': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extension-dropcursor': 3.30.4(@tiptap/extensions@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) - '@tiptap/extension-gapcursor': 3.30.4(@tiptap/extensions@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) - '@tiptap/extension-hard-break': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extension-heading': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extension-horizontal-rule': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) - '@tiptap/extension-italic': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extension-link': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) - '@tiptap/extension-list': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) - '@tiptap/extension-list-item': 3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) - '@tiptap/extension-list-keymap': 3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) - '@tiptap/extension-ordered-list': 3.30.4(@tiptap/extension-list@3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)) - '@tiptap/extension-paragraph': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extension-strike': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extension-text': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extension-underline': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4)) - '@tiptap/extensions': 3.30.4(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 - - '@tiptap/suggestion@3.30.4(@floating-ui/dom@1.8.0)(@tiptap/core@3.30.4(@tiptap/pm@3.30.4))(@tiptap/pm@3.30.4)': + '@tiptap/starter-kit@3.31.3': + dependencies: + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/extension-blockquote': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) + '@tiptap/extension-bold': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extension-bullet-list': 3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) + '@tiptap/extension-code': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extension-code-block': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) + '@tiptap/extension-document': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extension-dropcursor': 3.31.3(@tiptap/extensions@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) + '@tiptap/extension-gapcursor': 3.31.3(@tiptap/extensions@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) + '@tiptap/extension-hard-break': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extension-heading': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extension-horizontal-rule': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) + '@tiptap/extension-italic': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extension-link': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) + '@tiptap/extension-list': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) + '@tiptap/extension-list-item': 3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) + '@tiptap/extension-list-keymap': 3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) + '@tiptap/extension-ordered-list': 3.31.3(@tiptap/extension-list@3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)) + '@tiptap/extension-paragraph': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extension-strike': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extension-text': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extension-underline': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3)) + '@tiptap/extensions': 3.31.3(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 + + '@tiptap/suggestion@3.31.3(@floating-ui/dom@1.8.0)(@tiptap/core@3.31.3(@tiptap/pm@3.31.3))(@tiptap/pm@3.31.3)': dependencies: '@floating-ui/dom': 1.8.0 - '@tiptap/core': 3.30.4(@tiptap/pm@3.30.4) - '@tiptap/pm': 3.30.4 + '@tiptap/core': 3.31.3(@tiptap/pm@3.31.3) + '@tiptap/pm': 3.31.3 '@tybys/wasm-util@0.10.3': dependencies: @@ -5745,9 +5745,9 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-next@16.3.1(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3): + eslint-config-next@16.3.3(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3): dependencies: - '@next/eslint-plugin-next': 16.3.1(eslint@9.39.5(jiti@2.7.0)) + '@next/eslint-plugin-next': 16.3.3(eslint@9.39.5(jiti@2.7.0)) eslint: 9.39.5(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)) @@ -6155,11 +6155,11 @@ snapshots: highlight.js@11.11.1: {} - hono-rate-limiter@0.5.3(hono@4.13.2): + hono-rate-limiter@0.5.3(hono@4.13.7): dependencies: - hono: 4.13.2 + hono: 4.13.7 - hono@4.13.2: {} + hono@4.13.7: {} html-url-attributes@3.0.1: {} @@ -6343,7 +6343,7 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@4.3.1: + js-yaml@4.3.2: dependencies: argparse: 2.0.1 @@ -6890,9 +6890,9 @@ snapshots: negotiator@0.6.3: {} - next@16.3.1(@babel/core@7.29.7)(@types/node@26.2.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8): + next@16.3.3(@babel/core@7.29.7)(@types/node@26.2.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: - '@next/env': 16.3.1 + '@next/env': 16.3.3 '@swc/helpers': 0.5.23 baseline-browser-mapping: 2.11.14 caniuse-lite: 1.0.30001809 @@ -6901,15 +6901,15 @@ snapshots: react-dom: 19.2.8(react@19.2.8) styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.8) optionalDependencies: - '@next/swc-darwin-arm64': 16.3.1 - '@next/swc-darwin-x64': 16.3.1 - '@next/swc-linux-arm64-gnu': 16.3.1 - '@next/swc-linux-arm64-musl': 16.3.1 - '@next/swc-linux-x64-gnu': 16.3.1 - '@next/swc-linux-x64-musl': 16.3.1 - '@next/swc-win32-arm64-msvc': 16.3.1 - '@next/swc-win32-x64-msvc': 16.3.1 - sharp: 0.35.3(@types/node@26.2.0) + '@next/swc-darwin-arm64': 16.3.3 + '@next/swc-darwin-x64': 16.3.3 + '@next/swc-linux-arm64-gnu': 16.3.3 + '@next/swc-linux-arm64-musl': 16.3.3 + '@next/swc-linux-x64-gnu': 16.3.3 + '@next/swc-linux-x64-musl': 16.3.3 + '@next/swc-win32-arm64-msvc': 16.3.3 + '@next/swc-win32-x64-msvc': 16.3.3 + sharp: 0.35.4(@types/node@26.2.0) transitivePeerDependencies: - '@babel/core' - '@types/node' @@ -7393,37 +7393,37 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.2 - sharp@0.35.3(@types/node@26.2.0): + sharp@0.35.4(@types/node@26.2.0): dependencies: '@img/colour': 1.1.0 detect-libc: 2.1.2 semver: 7.8.5 optionalDependencies: - '@img/sharp-darwin-arm64': 0.35.3 - '@img/sharp-darwin-x64': 0.35.3 - '@img/sharp-freebsd-wasm32': 0.35.3 - '@img/sharp-libvips-darwin-arm64': 1.3.2 - '@img/sharp-libvips-darwin-x64': 1.3.2 - '@img/sharp-libvips-linux-arm': 1.3.2 - '@img/sharp-libvips-linux-arm64': 1.3.2 - '@img/sharp-libvips-linux-ppc64': 1.3.2 - '@img/sharp-libvips-linux-riscv64': 1.3.2 - '@img/sharp-libvips-linux-s390x': 1.3.2 - '@img/sharp-libvips-linux-x64': 1.3.2 - '@img/sharp-libvips-linuxmusl-arm64': 1.3.2 - '@img/sharp-libvips-linuxmusl-x64': 1.3.2 - '@img/sharp-linux-arm': 0.35.3 - '@img/sharp-linux-arm64': 0.35.3 - '@img/sharp-linux-ppc64': 0.35.3 - '@img/sharp-linux-riscv64': 0.35.3 - '@img/sharp-linux-s390x': 0.35.3 - '@img/sharp-linux-x64': 0.35.3 - '@img/sharp-linuxmusl-arm64': 0.35.3 - '@img/sharp-linuxmusl-x64': 0.35.3 - '@img/sharp-webcontainers-wasm32': 0.35.3 - '@img/sharp-win32-arm64': 0.35.3 - '@img/sharp-win32-ia32': 0.35.3 - '@img/sharp-win32-x64': 0.35.3 + '@img/sharp-darwin-arm64': 0.35.4 + '@img/sharp-darwin-x64': 0.35.4 + '@img/sharp-freebsd-wasm32': 0.35.4 + '@img/sharp-libvips-darwin-arm64': 1.3.3 + '@img/sharp-libvips-darwin-x64': 1.3.3 + '@img/sharp-libvips-linux-arm': 1.3.3 + '@img/sharp-libvips-linux-arm64': 1.3.3 + '@img/sharp-libvips-linux-ppc64': 1.3.3 + '@img/sharp-libvips-linux-riscv64': 1.3.3 + '@img/sharp-libvips-linux-s390x': 1.3.3 + '@img/sharp-libvips-linux-x64': 1.3.3 + '@img/sharp-libvips-linuxmusl-arm64': 1.3.3 + '@img/sharp-libvips-linuxmusl-x64': 1.3.3 + '@img/sharp-linux-arm': 0.35.4 + '@img/sharp-linux-arm64': 0.35.4 + '@img/sharp-linux-ppc64': 0.35.4 + '@img/sharp-linux-riscv64': 0.35.4 + '@img/sharp-linux-s390x': 0.35.4 + '@img/sharp-linux-x64': 0.35.4 + '@img/sharp-linuxmusl-arm64': 0.35.4 + '@img/sharp-linuxmusl-x64': 0.35.4 + '@img/sharp-webcontainers-wasm32': 0.35.4 + '@img/sharp-win32-arm64': 0.35.4 + '@img/sharp-win32-ia32': 0.35.4 + '@img/sharp-win32-x64': 0.35.4 '@types/node': 26.2.0 optional: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 40d386b9..5afcb2c0 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -10,13 +10,13 @@ overrides: engine.io: ^6.6.7 esbuild: ^0.28.1 fast-uri: ^3.1.5 - hono: ^4.12.34 + hono: ^4.13.5 ip-address: ^10.3.1 - js-yaml: ^4.3.1 + js-yaml: ^4.3.2 nanoid: ^3.3.17 postcss: ^8.5.23 qs: ^6.15.2 - sharp: ^0.35.3 + sharp: ^0.35.4 socket.io-parser: ^4.2.7 ws: ^8.21.0 allowBuilds: diff --git a/scripts/product-browser-smoke.mjs b/scripts/product-browser-smoke.mjs index 1a4d2f44..a61af459 100644 --- a/scripts/product-browser-smoke.mjs +++ b/scripts/product-browser-smoke.mjs @@ -107,7 +107,7 @@ async function main() { ['/settings', 'Settings'], ['/settings/profile', 'Profile'], ['/settings/apps', 'Apps'], - ['/settings/mcp-access', 'What do you want to connect?'], + ['/settings/mcp-access', 'Your connections'], ]) { await settle(page, path); await page.getByRole('heading', { name: heading }).first().waitFor({ timeout: 10_000 }); @@ -117,6 +117,62 @@ async function main() { } record('Navigate core settings surfaces'); + await page.getByRole('searchbox', { name: 'Search connections' }).fill('no-such-smoke-connection'); + await page.getByRole('heading', { name: 'No matching connections' }).waitFor(); + await page.getByRole('button', { name: 'Clear search', exact: true }).click(); + await page.getByRole('button', { name: 'Add connection', exact: true }).click(); + await page.getByRole('heading', { name: 'Which app would you like to connect?', exact: true }).waitFor(); + await page.getByRole('button', { name: /^Claude Code Use a personal token/ }).click(); + await page.getByRole('button', { name: 'Review access', exact: true }).click(); + await page.getByRole('combobox', { name: 'Access level', exact: true }).selectOption('custom'); + for (const width of [1440, 1024, 768, 390]) { + await page.setViewportSize({ width, height: 900 }); + const setupOverflow = await page.locator('section[aria-labelledby="setup-heading"]').evaluate((section) => section.scrollWidth - section.clientWidth); + if (setupOverflow > 2) throw new Error(`Claude Code setup overflows its cards by ${setupOverflow}px at ${width}px`); + await page.getByRole('button', { name: 'Continue to connect', exact: true }).click(); + await page.getByRole('textbox', { name: 'Connection name', exact: true }).fill('Smoke test draft'); + const commandOverflow = await page.getByRole('textbox', { name: 'Connection name', exact: true }).evaluate((input) => { + const section = input.closest('section'); + return section.scrollWidth - section.clientWidth; + }); + if (commandOverflow > 2) throw new Error(`Claude Code command expands its card at ${width}px`); + await page.getByRole('button', { name: 'Back', exact: true }).click(); + await page.getByRole('button', { name: 'Continue to connect', exact: true }).click(); + if (await page.getByRole('textbox', { name: 'Connection name', exact: true }).inputValue() !== 'Smoke test draft') { + throw new Error('Connection name was lost between setup steps'); + } + await page.getByRole('button', { name: 'Back', exact: true }).click(); + } + record('Claude Code custom permissions stay inside setup cards at desktop, tablet and mobile widths'); + + for (const checkbox of await page.getByRole('checkbox').all()) await checkbox.uncheck(); + if (await page.getByRole('button', { name: 'Continue to connect', exact: true }).isEnabled()) { + throw new Error('Setup permits an empty permission selection'); + } + await page.getByRole('checkbox', { name: 'Read tasks, comments and progress', exact: true }).check(); + await page.getByRole('button', { name: 'Continue to connect', exact: true }).click(); + const personalConnectionName = `Browser smoke ${Date.now()}`; + await page.getByRole('textbox', { name: 'Connection name', exact: true }).fill(personalConnectionName); + await page.getByRole('button', { name: 'Generate token', exact: true }).click(); + await page.getByRole('checkbox', { name: 'I have saved this token securely.', exact: true }).waitFor({ timeout: 10_000 }); + if (await page.getByRole('button', { name: 'Check connection', exact: true }).isEnabled()) { + throw new Error('Setup skipped the one-time token acknowledgement'); + } + await page.getByRole('checkbox', { name: 'I have saved this token securely.', exact: true }).check(); + await page.getByRole('button', { name: 'Check connection', exact: true }).click(); + await page.getByRole('heading', { name: 'Waiting for the first request', exact: true }).waitFor(); + await page.getByRole('button', { name: 'Your connections', exact: true }).click(); + await page.getByRole('searchbox', { name: 'Search connections' }).fill(personalConnectionName); + await page.getByText(personalConnectionName, { exact: true }).click(); + await page.getByRole('button', { name: 'Revoke access', exact: true }).click(); + await page.getByRole('button', { name: 'Keep connection', exact: true }).click(); + await page.getByRole('button', { name: 'Revoke access', exact: true }).click(); + await page.getByRole('button', { name: 'Confirm revoke', exact: true }).click(); + await page.getByRole('heading', { name: 'No matching connections', exact: true }).waitFor(); + await page.getByRole('button', { name: /^Connection history/ }).click(); + await page.locator('summary').filter({ hasText: personalConnectionName }).waitFor(); + record('Create, acknowledge, inspect and revoke a personal connection without exposing its token'); + await page.setViewportSize({ width: 1440, height: 900 }); await settle(page, '/settings/modules'); const availableTab = page.getByRole('button', { name: /Available/i }).first();