@agent-native/core 0.127.3 → 0.128.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +80 -0
- package/corpus/core/README.md +5 -26
- package/corpus/core/docs/content/actions.mdx +47 -4
- package/corpus/core/docs/content/native-chat-ui.mdx +7 -0
- package/corpus/core/docs/content/organizations-teams-permissions.mdx +109 -3
- package/corpus/core/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
- package/corpus/core/docs/content/toolkit-org-team.mdx +72 -12
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/artifact-response.ts +36 -29
- package/corpus/core/src/action.ts +83 -2
- package/corpus/core/src/chat-threads/store.ts +48 -43
- package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
- package/corpus/core/src/client/AgentPanel.tsx +26 -6
- package/corpus/core/src/client/AssistantChat.tsx +63 -7
- package/corpus/core/src/client/DefaultSpinner.tsx +29 -0
- package/corpus/core/src/client/org/TeamPage.tsx +161 -6
- package/corpus/core/src/client/org/hooks.ts +67 -0
- package/corpus/core/src/client/org/index.ts +9 -0
- package/corpus/core/src/client/transcription/use-live-transcription.ts +62 -10
- package/corpus/core/src/db/client.ts +42 -3
- package/corpus/core/src/db/ensure-additive-columns.ts +60 -33
- package/corpus/core/src/deploy/build.ts +31 -2
- package/corpus/core/src/mcp-client/routes.ts +10 -1
- package/corpus/core/src/org/app-roles-handlers.ts +152 -0
- package/corpus/core/src/org/app-roles.ts +355 -0
- package/corpus/core/src/org/index.ts +27 -1
- package/corpus/core/src/org/migrations.ts +22 -0
- package/corpus/core/src/org/plugin.ts +27 -0
- package/corpus/core/src/org/schema.ts +15 -0
- package/corpus/core/src/scripts/docs/search.ts +17 -0
- package/corpus/core/src/scripts/docs/source-search.ts +10 -0
- package/corpus/core/src/server/agent-chat/script-entries.ts +3 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +53 -52
- package/corpus/core/src/server/core-routes-plugin.ts +6 -1
- package/corpus/core/src/server/framework-request-handler.ts +44 -6
- package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +31 -0
- package/corpus/core/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/analytics/actions/data-source-status.ts +21 -12
- package/corpus/templates/analytics/app/global.css +7 -7
- package/corpus/templates/analytics/app/i18n-data.ts +30 -0
- package/corpus/templates/analytics/app/lib/data-source-status.ts +2 -1
- package/corpus/templates/analytics/app/pages/DataSources.tsx +54 -10
- package/corpus/templates/analytics/changelog/2026-07-28-analytics-pages-load-reliably-with-large-dashboard-workspaces.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-28-dashboard-loading-shimmer-now-flows-smoothly-in-one-directi.md +6 -0
- package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +5 -4
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +54 -42
- package/corpus/templates/analytics/server/plugins/db.ts +1 -18
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/clips/actions/request-transcript.ts +77 -11
- package/corpus/templates/clips/actions/save-browser-transcript.ts +28 -7
- package/corpus/templates/clips/app/routes/record.tsx +11 -3
- package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-save-a-truncated-transcript-as-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-stop-transcribing-partway-throu.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-desktop-full-screen-clips-now-get-an-instant-local-transcrip.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-long-transcriptions-no-longer-show-a-false-transcription-sto.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-restarting-for-an-update-now-installs-the-newest-release-ins.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-the-meeting-recording-pill-now-anchors-to-the-right-edge-of-.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/audio-meter.ts +31 -2
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +114 -13
- package/corpus/templates/clips/desktop/src/lib/updater.ts +12 -4
- package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +40 -15
- package/corpus/templates/clips/desktop/src/styles.css +10 -7
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +21 -14
- package/corpus/templates/clips/shared/transcript-status.ts +10 -0
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/content/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/content/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/design/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +46 -3
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +7 -5
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +2 -2
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +7 -4
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +1 -1
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +10 -4
- package/corpus/templates/design/app/lib/design-ui-events.ts +5 -0
- package/corpus/templates/design/app/root.tsx +18 -1
- package/corpus/templates/design/changelog/2026-07-28-show-or-hide-design-editing-chrome-with-cmd-on-apple-devices.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/macros/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/tasks/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/tasks/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +4 -0
- package/dist/a2a/artifact-response.d.ts.map +1 -1
- package/dist/a2a/artifact-response.js +30 -29
- package/dist/a2a/artifact-response.js.map +1 -1
- package/dist/action.d.ts +36 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +37 -2
- package/dist/action.js.map +1 -1
- package/dist/chat-threads/store.d.ts +12 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +48 -42
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.js +46 -3
- package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +11 -9
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +57 -6
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/DefaultSpinner.d.ts +7 -0
- package/dist/client/DefaultSpinner.d.ts.map +1 -1
- package/dist/client/DefaultSpinner.js +25 -1
- package/dist/client/DefaultSpinner.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts +13 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +41 -11
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/org/hooks.d.ts +37 -0
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/org/hooks.js +37 -0
- package/dist/client/org/hooks.js.map +1 -1
- package/dist/client/org/index.d.ts +3 -2
- package/dist/client/org/index.d.ts.map +1 -1
- package/dist/client/org/index.js +1 -1
- package/dist/client/org/index.js.map +1 -1
- package/dist/client/transcription/use-live-transcription.d.ts +8 -0
- package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
- package/dist/client/transcription/use-live-transcription.js +38 -11
- package/dist/client/transcription/use-live-transcription.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/client.d.ts +12 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +40 -3
- package/dist/db/client.js.map +1 -1
- package/dist/db/ensure-additive-columns.d.ts.map +1 -1
- package/dist/db/ensure-additive-columns.js +54 -32
- package/dist/db/ensure-additive-columns.js.map +1 -1
- package/dist/deploy/build.d.ts +1 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +23 -2
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/mcp-client/routes.d.ts +3 -1
- package/dist/mcp-client/routes.d.ts.map +1 -1
- package/dist/mcp-client/routes.js +8 -2
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/org/app-roles-handlers.d.ts +27 -0
- package/dist/org/app-roles-handlers.d.ts.map +1 -0
- package/dist/org/app-roles-handlers.js +125 -0
- package/dist/org/app-roles-handlers.js.map +1 -0
- package/dist/org/app-roles.d.ts +136 -0
- package/dist/org/app-roles.d.ts.map +1 -0
- package/dist/org/app-roles.js +216 -0
- package/dist/org/app-roles.js.map +1 -0
- package/dist/org/index.d.ts +4 -1
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +3 -1
- package/dist/org/index.js.map +1 -1
- package/dist/org/migrations.d.ts.map +1 -1
- package/dist/org/migrations.js +22 -0
- package/dist/org/migrations.js.map +1 -1
- package/dist/org/plugin.d.ts +2 -0
- package/dist/org/plugin.d.ts.map +1 -1
- package/dist/org/plugin.js +20 -0
- package/dist/org/plugin.js.map +1 -1
- package/dist/org/schema.d.ts +143 -0
- package/dist/org/schema.d.ts.map +1 -1
- package/dist/org/schema.js +14 -0
- package/dist/org/schema.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +12 -12
- package/dist/scripts/docs/search.d.ts.map +1 -1
- package/dist/scripts/docs/search.js +15 -0
- package/dist/scripts/docs/search.js.map +1 -1
- package/dist/scripts/docs/source-search.d.ts +7 -0
- package/dist/scripts/docs/source-search.d.ts.map +1 -1
- package/dist/scripts/docs/source-search.js +9 -0
- package/dist/scripts/docs/source-search.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/script-entries.d.ts.map +1 -1
- package/dist/server/agent-chat/script-entries.js +3 -0
- package/dist/server/agent-chat/script-entries.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +46 -48
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +6 -1
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +42 -6
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/templates/chat/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/dist/templates/chat/.agents/skills/security/SKILL.md +31 -0
- package/dist/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/dist/templates/default/.agents/skills/security/SKILL.md +31 -0
- package/dist/templates/headless/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
- package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
- package/docs/content/actions.mdx +47 -4
- package/docs/content/native-chat-ui.mdx +7 -0
- package/docs/content/organizations-teams-permissions.mdx +109 -3
- package/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
- package/docs/content/toolkit-org-team.mdx +72 -12
- package/package.json +1 -1
- package/src/a2a/artifact-response.ts +36 -29
- package/src/action.ts +83 -2
- package/src/chat-threads/store.ts +48 -43
- package/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
- package/src/client/AgentPanel.tsx +26 -6
- package/src/client/AssistantChat.tsx +63 -7
- package/src/client/DefaultSpinner.tsx +29 -0
- package/src/client/org/TeamPage.tsx +161 -6
- package/src/client/org/hooks.ts +67 -0
- package/src/client/org/index.ts +9 -0
- package/src/client/transcription/use-live-transcription.ts +62 -10
- package/src/db/client.ts +42 -3
- package/src/db/ensure-additive-columns.ts +60 -33
- package/src/deploy/build.ts +31 -2
- package/src/mcp-client/routes.ts +10 -1
- package/src/org/app-roles-handlers.ts +152 -0
- package/src/org/app-roles.ts +355 -0
- package/src/org/index.ts +27 -1
- package/src/org/migrations.ts +22 -0
- package/src/org/plugin.ts +27 -0
- package/src/org/schema.ts +15 -0
- package/src/scripts/docs/search.ts +17 -0
- package/src/scripts/docs/source-search.ts +10 -0
- package/src/server/agent-chat/script-entries.ts +3 -0
- package/src/server/agent-chat-plugin.ts +53 -52
- package/src/server/core-routes-plugin.ts +6 -1
- package/src/server/framework-request-handler.ts +44 -6
- package/src/templates/chat/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/src/templates/chat/.agents/skills/security/SKILL.md +31 -0
- package/src/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
- package/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/src/templates/default/.agents/skills/security/SKILL.md +31 -0
- package/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
- package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/core/src/templates/chat/.agents/skills/actions/SKILL.md +0 -530
- package/corpus/core/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +0 -191
- package/corpus/core/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +0 -115
- package/corpus/core/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +0 -177
- package/corpus/core/src/templates/chat/.agents/skills/capture-learnings/SKILL.md +0 -89
- package/corpus/core/src/templates/chat/.agents/skills/create-skill/SKILL.md +0 -221
- package/corpus/core/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +0 -220
- package/corpus/core/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +0 -263
- package/corpus/core/src/templates/chat/.agents/skills/feature-flags/SKILL.md +0 -169
- package/corpus/core/src/templates/chat/.agents/skills/frontend-design/SKILL.md +0 -174
- package/corpus/core/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +0 -232
- package/corpus/core/src/templates/chat/.agents/skills/security/SKILL.md +0 -282
- package/corpus/core/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +0 -119
- package/corpus/core/src/templates/chat/.agents/skills/shadcn-ui/SKILL.md +0 -123
- package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +0 -122
- package/corpus/core/src/templates/chat/.env.example +0 -5
- package/corpus/core/src/templates/chat/.ignore +0 -0
- package/corpus/core/src/templates/chat/.oxfmtrc.json +0 -8
- package/corpus/core/src/templates/chat/AGENTS.md +0 -77
- package/corpus/core/src/templates/chat/CHANGELOG.md +0 -10
- package/corpus/core/src/templates/chat/DEVELOPING.md +0 -185
- package/corpus/core/src/templates/chat/README.md +0 -32
- package/corpus/core/src/templates/chat/_gitignore +0 -46
- package/corpus/core/src/templates/chat/actions/hello.ts +0 -13
- package/corpus/core/src/templates/chat/actions/navigate.ts +0 -41
- package/corpus/core/src/templates/chat/actions/run.ts +0 -2
- package/corpus/core/src/templates/chat/actions/view-screen.ts +0 -31
- package/corpus/core/src/templates/chat/app/components/layout/Header.tsx +0 -60
- package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +0 -188
- package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +0 -505
- package/corpus/core/src/templates/chat/app/components/ui/button.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/card.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/dropdown-menu.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/input.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/label.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/sheet.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/toolkit-provider.tsx +0 -17
- package/corpus/core/src/templates/chat/app/components/ui/tooltip.tsx +0 -1
- package/corpus/core/src/templates/chat/app/design-system.ts +0 -3
- package/corpus/core/src/templates/chat/app/entry.client.tsx +0 -22
- package/corpus/core/src/templates/chat/app/entry.server.tsx +0 -10
- package/corpus/core/src/templates/chat/app/global.css +0 -93
- package/corpus/core/src/templates/chat/app/hooks/use-navigation-state.ts +0 -93
- package/corpus/core/src/templates/chat/app/i18n/ar-SA.ts +0 -68
- package/corpus/core/src/templates/chat/app/i18n/de-DE.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/en-US.ts +0 -70
- package/corpus/core/src/templates/chat/app/i18n/es-ES.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/fr-FR.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/hi-IN.ts +0 -69
- package/corpus/core/src/templates/chat/app/i18n/index.ts +0 -34
- package/corpus/core/src/templates/chat/app/i18n/ja-JP.ts +0 -70
- package/corpus/core/src/templates/chat/app/i18n/ko-KR.ts +0 -70
- package/corpus/core/src/templates/chat/app/i18n/pt-BR.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/zh-CN.ts +0 -66
- package/corpus/core/src/templates/chat/app/i18n/zh-TW.ts +0 -66
- package/corpus/core/src/templates/chat/app/i18n-data.ts +0 -556
- package/corpus/core/src/templates/chat/app/lib/agent-page.tsx +0 -49
- package/corpus/core/src/templates/chat/app/lib/app-config.ts +0 -11
- package/corpus/core/src/templates/chat/app/lib/tab-id.ts +0 -1
- package/corpus/core/src/templates/chat/app/lib/utils.ts +0 -1
- package/corpus/core/src/templates/chat/app/root.tsx +0 -173
- package/corpus/core/src/templates/chat/app/routes/_index.tsx +0 -94
- package/corpus/core/src/templates/chat/app/routes/agent.tsx +0 -24
- package/corpus/core/src/templates/chat/app/routes/chat.$threadId.tsx +0 -1
- package/corpus/core/src/templates/chat/app/routes/database.tsx +0 -17
- package/corpus/core/src/templates/chat/app/routes/extensions.$id.$slug.tsx +0 -2
- package/corpus/core/src/templates/chat/app/routes/extensions.$id.tsx +0 -11
- package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +0 -11
- package/corpus/core/src/templates/chat/app/routes/extensions.tsx +0 -5
- package/corpus/core/src/templates/chat/app/routes/observability.tsx +0 -19
- package/corpus/core/src/templates/chat/app/routes/settings.tsx +0 -89
- package/corpus/core/src/templates/chat/app/routes/team.tsx +0 -11
- package/corpus/core/src/templates/chat/app/routes.ts +0 -4
- package/corpus/core/src/templates/chat/app/vite-env.d.ts +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +0 -5
- package/corpus/core/src/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +0 -6
- package/corpus/core/src/templates/chat/components.json +0 -20
- package/corpus/core/src/templates/chat/learnings.defaults.md +0 -5
- package/corpus/core/src/templates/chat/netlify.toml +0 -11
- package/corpus/core/src/templates/chat/package.json +0 -92
- package/corpus/core/src/templates/chat/public/agent-native-icon-dark.svg +0 -10
- package/corpus/core/src/templates/chat/public/agent-native-icon-light.svg +0 -10
- package/corpus/core/src/templates/chat/public/agent-native-logo-dark.svg +0 -21
- package/corpus/core/src/templates/chat/public/agent-native-logo-light.svg +0 -21
- package/corpus/core/src/templates/chat/public/favicon.svg +0 -1
- package/corpus/core/src/templates/chat/public/icon-180.svg +0 -1
- package/corpus/core/src/templates/chat/public/icon-192.svg +0 -1
- package/corpus/core/src/templates/chat/public/icon-512.svg +0 -1
- package/corpus/core/src/templates/chat/public/manifest.json +0 -21
- package/corpus/core/src/templates/chat/react-router.config.ts +0 -7
- package/corpus/core/src/templates/chat/server/middleware/auth.ts +0 -15
- package/corpus/core/src/templates/chat/server/plugins/agent-chat.ts +0 -21
- package/corpus/core/src/templates/chat/server/plugins/auth.ts +0 -17
- package/corpus/core/src/templates/chat/server/routes/[...page].get.ts +0 -5
- package/corpus/core/src/templates/chat/ssr-entry.ts +0 -15
- package/corpus/core/src/templates/chat/tsconfig.json +0 -21
- package/corpus/core/src/templates/chat/vite.config.ts +0 -19
|
@@ -159,6 +159,35 @@ whole site. Data scoping lives in actions and API routes; the client gates
|
|
|
159
159
|
private UI after the shell loads. See the `authentication` skill and
|
|
160
160
|
`guard:ssr-cache-shell` / `ssr-handler.spec.ts`.
|
|
161
161
|
|
|
162
|
+
**Authorization beyond "is there a session" — `authorize`.** The auth guard only
|
|
163
|
+
proves *someone* is signed in. To restrict an operation to some teammates, set
|
|
164
|
+
`authorize` on the `defineAction`. It wraps `run`, so it applies at every
|
|
165
|
+
dispatch site (agent tool, HTTP, frontend, MCP, A2A, CLI) — unlike
|
|
166
|
+
`needsApproval`, which is honoured only in the agent loop.
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { coachAccess } from "../lib/access.js"; // defineAppRoles(...)
|
|
170
|
+
|
|
171
|
+
export default defineAction({
|
|
172
|
+
description: "Archive a client roster.",
|
|
173
|
+
schema: z.object({ id: z.string() }),
|
|
174
|
+
authorize: coachAccess.requireAny("coach-admin"),
|
|
175
|
+
run: async (args) => {
|
|
176
|
+
/* ... */
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
A guard that throws denies with its own message; returning `false` denies
|
|
182
|
+
generically; anything else (including `undefined`) allows. Guarded actions need
|
|
183
|
+
a user identity — an unattended CLI/cron caller with no user email is denied.
|
|
184
|
+
|
|
185
|
+
`authorize` is **not** a substitute for `accessFilter` / `assertAccess`. It
|
|
186
|
+
decides whether this caller may perform the operation at all; `accessFilter` /
|
|
187
|
+
`assertAccess` scope which rows a permitted caller may see or touch. A
|
|
188
|
+
restricted write action needs both. See the `authentication` skill for
|
|
189
|
+
`defineAppRoles` and the `actions` skill for the full surface.
|
|
190
|
+
|
|
162
191
|
## Human-in-the-Loop Approval for High-Consequence Actions
|
|
163
192
|
|
|
164
193
|
For a small set of outward-facing, hard-to-undo operations — sending an email, charging a card, deleting an account, posting publicly — auth and access control are necessary but not sufficient: you also do not want the **agent** to perform them autonomously. Set `needsApproval` on the `defineAction` so the agent cannot run the action without a human approving the specific call.
|
|
@@ -274,6 +303,8 @@ Run `pnpm action db-check-scoping` to verify. Use `--require-org` for multi-org
|
|
|
274
303
|
- [ ] New env vars in `.env` only, not committed
|
|
275
304
|
- [ ] New user-data tables have `owner_email` column
|
|
276
305
|
- [ ] Custom routes call `getSession` and reject unauthenticated requests
|
|
306
|
+
- [ ] Actions only some teammates may run set `authorize` (in addition to any
|
|
307
|
+
`accessFilter` / `assertAccess` row scoping)
|
|
277
308
|
|
|
278
309
|
## Related Skills
|
|
279
310
|
|
|
@@ -34,6 +34,8 @@ Visibility is coarse. Explicit share grants are fine-grained (per user or per or
|
|
|
34
34
|
- **`editor`** — read + write.
|
|
35
35
|
- **`admin`** — read + write + manage shares. Does NOT replace the single `owner_email` on the resource.
|
|
36
36
|
|
|
37
|
+
There are three role systems and they never imply one another. A share role answers "what may this person do to **one row**". An org role (`org_members.role`) answers "what may this person do to the **team**". An app role (`defineAppRoles`, see the `authentication` skill) answers "what may this person do inside **one app**". A share `admin` is not an app admin and neither is an org admin.
|
|
38
|
+
|
|
37
39
|
### Anonymous public URLs stay separate
|
|
38
40
|
|
|
39
41
|
Form "publish" slugs, booking-link slugs, any feature that exposes a URL to unauthenticated users — these are a different axis and are NOT controlled by the sharing system. Keep them alongside it.
|
|
@@ -137,6 +139,8 @@ export default defineAction({
|
|
|
137
139
|
|
|
138
140
|
For delete actions use `"admin"` (or fold in `"owner"` to require the real owner).
|
|
139
141
|
|
|
142
|
+
`authorize` is a different axis, not an alternative: it gates whether the caller may run the operation at all, while `assertAccess` scopes which row they may touch. A write action restricted to some teammates needs both — `authorize: appAccess.requireAny(...)` on the action, `assertAccess` inside `run`.
|
|
143
|
+
|
|
140
144
|
## Create actions must set owner
|
|
141
145
|
|
|
142
146
|
When inserting a new row, fill `ownerEmail` and `orgId` from the request context:
|
|
@@ -34,6 +34,8 @@ Visibility is coarse. Explicit share grants are fine-grained (per user or per or
|
|
|
34
34
|
- **`editor`** — read + write.
|
|
35
35
|
- **`admin`** — read + write + manage shares. Does NOT replace the single `owner_email` on the resource.
|
|
36
36
|
|
|
37
|
+
There are three role systems and they never imply one another. A share role answers "what may this person do to **one row**". An org role (`org_members.role`) answers "what may this person do to the **team**". An app role (`defineAppRoles`, see the `authentication` skill) answers "what may this person do inside **one app**". A share `admin` is not an app admin and neither is an org admin.
|
|
38
|
+
|
|
37
39
|
### Anonymous public URLs stay separate
|
|
38
40
|
|
|
39
41
|
Form "publish" slugs, booking-link slugs, any feature that exposes a URL to unauthenticated users — these are a different axis and are NOT controlled by the sharing system. Keep them alongside it.
|
|
@@ -137,6 +139,8 @@ export default defineAction({
|
|
|
137
139
|
|
|
138
140
|
For delete actions use `"admin"` (or fold in `"owner"` to require the real owner).
|
|
139
141
|
|
|
142
|
+
`authorize` is a different axis, not an alternative: it gates whether the caller may run the operation at all, while `assertAccess` scopes which row they may touch. A write action restricted to some teammates needs both — `authorize: appAccess.requireAny(...)` on the action, `assertAccess` inside `run`.
|
|
143
|
+
|
|
140
144
|
## Create actions must set owner
|
|
141
145
|
|
|
142
146
|
When inserting a new row, fill `ownerEmail` and `orgId` from the request context:
|
|
@@ -305,6 +305,38 @@ export default defineAction({
|
|
|
305
305
|
|
|
306
306
|
On success the validated value is returned, so coercion/defaults on `outputSchema` apply. Omit `outputSchema` and behavior is byte-for-byte unchanged (no wrapping).
|
|
307
307
|
|
|
308
|
+
### Authorization (`authorize`)
|
|
309
|
+
|
|
310
|
+
`authorize` decides whether the caller may run the action at all. It wraps
|
|
311
|
+
`run`, so it holds at **all six dispatch sites** — agent tool, HTTP, frontend
|
|
312
|
+
hook, MCP, A2A, CLI — unlike `needsApproval`, which is honoured only in the
|
|
313
|
+
agent loop. Use `authorize` for "not everyone may do this"; use `needsApproval`
|
|
314
|
+
to ask a human to bless one call a permitted caller is already allowed to make.
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
import { coachAccess } from "../lib/access.js"; // defineAppRoles(...)
|
|
318
|
+
|
|
319
|
+
export default defineAction({
|
|
320
|
+
description: "Archive a client roster.",
|
|
321
|
+
schema: z.object({ id: z.string() }),
|
|
322
|
+
authorize: coachAccess.requireAny("coach-admin"),
|
|
323
|
+
run: async (args) => {
|
|
324
|
+
/* ... */
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
The wrappers compose as `validate input -> authorize -> run -> validate output
|
|
330
|
+
-> audit`: the gate sits inside input validation, so a guard reading `args` gets
|
|
331
|
+
the parsed, coerced value, and auditing is outermost, so denials are recorded.
|
|
332
|
+
|
|
333
|
+
A guard that throws denies with its own message; returning `false` denies
|
|
334
|
+
generically; anything else (including `undefined`) allows. A guarded action
|
|
335
|
+
needs a user identity, so an unattended CLI/cron caller with no user email is
|
|
336
|
+
denied. `authorize` gates the operation; `accessFilter` / `assertAccess` still
|
|
337
|
+
scope which rows a permitted caller may touch. See the `authentication` skill
|
|
338
|
+
for `defineAppRoles` and the `sharing` skill for row scoping.
|
|
339
|
+
|
|
308
340
|
### Human-in-the-Loop Approval (`needsApproval`)
|
|
309
341
|
|
|
310
342
|
For high-consequence, outward-facing, hard-to-undo actions (sending an email, charging a card, deleting an account), set `needsApproval` so the agent **cannot** run the action without a human approving the specific call:
|
|
@@ -159,6 +159,35 @@ whole site. Data scoping lives in actions and API routes; the client gates
|
|
|
159
159
|
private UI after the shell loads. See the `authentication` skill and
|
|
160
160
|
`guard:ssr-cache-shell` / `ssr-handler.spec.ts`.
|
|
161
161
|
|
|
162
|
+
**Authorization beyond "is there a session" — `authorize`.** The auth guard only
|
|
163
|
+
proves *someone* is signed in. To restrict an operation to some teammates, set
|
|
164
|
+
`authorize` on the `defineAction`. It wraps `run`, so it applies at every
|
|
165
|
+
dispatch site (agent tool, HTTP, frontend, MCP, A2A, CLI) — unlike
|
|
166
|
+
`needsApproval`, which is honoured only in the agent loop.
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { coachAccess } from "../lib/access.js"; // defineAppRoles(...)
|
|
170
|
+
|
|
171
|
+
export default defineAction({
|
|
172
|
+
description: "Archive a client roster.",
|
|
173
|
+
schema: z.object({ id: z.string() }),
|
|
174
|
+
authorize: coachAccess.requireAny("coach-admin"),
|
|
175
|
+
run: async (args) => {
|
|
176
|
+
/* ... */
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
A guard that throws denies with its own message; returning `false` denies
|
|
182
|
+
generically; anything else (including `undefined`) allows. Guarded actions need
|
|
183
|
+
a user identity — an unattended CLI/cron caller with no user email is denied.
|
|
184
|
+
|
|
185
|
+
`authorize` is **not** a substitute for `accessFilter` / `assertAccess`. It
|
|
186
|
+
decides whether this caller may perform the operation at all; `accessFilter` /
|
|
187
|
+
`assertAccess` scope which rows a permitted caller may see or touch. A
|
|
188
|
+
restricted write action needs both. See the `authentication` skill for
|
|
189
|
+
`defineAppRoles` and the `actions` skill for the full surface.
|
|
190
|
+
|
|
162
191
|
## Human-in-the-Loop Approval for High-Consequence Actions
|
|
163
192
|
|
|
164
193
|
For a small set of outward-facing, hard-to-undo operations — sending an email, charging a card, deleting an account, posting publicly — auth and access control are necessary but not sufficient: you also do not want the **agent** to perform them autonomously. Set `needsApproval` on the `defineAction` so the agent cannot run the action without a human approving the specific call.
|
|
@@ -274,6 +303,8 @@ Run `pnpm action db-check-scoping` to verify. Use `--require-org` for multi-org
|
|
|
274
303
|
- [ ] New env vars in `.env` only, not committed
|
|
275
304
|
- [ ] New user-data tables have `owner_email` column
|
|
276
305
|
- [ ] Custom routes call `getSession` and reject unauthenticated requests
|
|
306
|
+
- [ ] Actions only some teammates may run set `authorize` (in addition to any
|
|
307
|
+
`accessFilter` / `assertAccess` row scoping)
|
|
277
308
|
|
|
278
309
|
## Related Skills
|
|
279
310
|
|
|
@@ -34,6 +34,8 @@ Visibility is coarse. Explicit share grants are fine-grained (per user or per or
|
|
|
34
34
|
- **`editor`** — read + write.
|
|
35
35
|
- **`admin`** — read + write + manage shares. Does NOT replace the single `owner_email` on the resource.
|
|
36
36
|
|
|
37
|
+
There are three role systems and they never imply one another. A share role answers "what may this person do to **one row**". An org role (`org_members.role`) answers "what may this person do to the **team**". An app role (`defineAppRoles`, see the `authentication` skill) answers "what may this person do inside **one app**". A share `admin` is not an app admin and neither is an org admin.
|
|
38
|
+
|
|
37
39
|
### Anonymous public URLs stay separate
|
|
38
40
|
|
|
39
41
|
Form "publish" slugs, booking-link slugs, any feature that exposes a URL to unauthenticated users — these are a different axis and are NOT controlled by the sharing system. Keep them alongside it.
|
|
@@ -137,6 +139,8 @@ export default defineAction({
|
|
|
137
139
|
|
|
138
140
|
For delete actions use `"admin"` (or fold in `"owner"` to require the real owner).
|
|
139
141
|
|
|
142
|
+
`authorize` is a different axis, not an alternative: it gates whether the caller may run the operation at all, while `assertAccess` scopes which row they may touch. A write action restricted to some teammates needs both — `authorize: appAccess.requireAny(...)` on the action, `assertAccess` inside `run`.
|
|
143
|
+
|
|
140
144
|
## Create actions must set owner
|
|
141
145
|
|
|
142
146
|
When inserting a new row, fill `ownerEmail` and `orgId` from the request context:
|
|
@@ -25,6 +25,32 @@ hosted Design MCP connector together. The open Skills CLI path
|
|
|
25
25
|
(`npx skills@latest add BuilderIO/agent-native --skill visual-edit`) installs
|
|
26
26
|
exported instructions only, with no MCP connector registration.
|
|
27
27
|
|
|
28
|
+
## Put Design Beside The Chat
|
|
29
|
+
|
|
30
|
+
After `open-visual-edit` returns `openUrl`, open that URL in the coding host's
|
|
31
|
+
inline browser when one is available. This is the preferred working surface:
|
|
32
|
+
the user can keep Design's canvas beside the conversation, inspect the same
|
|
33
|
+
screens as the agent, and iterate without switching apps.
|
|
34
|
+
|
|
35
|
+
- In Codex Desktop, use the in-app Browser tool to open `openUrl`. The built-in
|
|
36
|
+
browser is the right surface for localhost and public pages that should stay
|
|
37
|
+
inside the app.
|
|
38
|
+
- In Claude Code Desktop's Code tab, open or preview `openUrl` in the Browser
|
|
39
|
+
pane. Ask Claude to preview it rather than opening the system browser.
|
|
40
|
+
- In VS Code, use the Agent Native Design webview/deep link described below.
|
|
41
|
+
- Inline browser availability is host-dependent. CLI, remote, or restricted
|
|
42
|
+
sessions may not expose one. If the inline surface is unavailable or disabled,
|
|
43
|
+
return the normal **Open design** link instead of claiming it opened.
|
|
44
|
+
|
|
45
|
+
Prefer the host's browser/preview tool over telling the user to press a keyboard
|
|
46
|
+
shortcut. Keep the canvas pane beside chat when the host supports rearrangeable
|
|
47
|
+
panes.
|
|
48
|
+
|
|
49
|
+
Inside Design, use **Show/Hide UI** from the `Cmd+K` menu or press
|
|
50
|
+
`Cmd+Shift+\` on Apple platforms / `Ctrl+Shift+\` elsewhere to toggle all
|
|
51
|
+
editing chrome so only the canvas remains. The same action is available from
|
|
52
|
+
Design's empty-canvas context menu.
|
|
53
|
+
|
|
28
54
|
## Core Model
|
|
29
55
|
|
|
30
56
|
- Each screen is a URL-backed iframe, not copied HTML.
|
|
@@ -54,6 +80,23 @@ exported instructions only, with no MCP connector registration.
|
|
|
54
80
|
`localhost:1234/onboarding/1` means
|
|
55
81
|
`http://localhost:1234/onboarding/1`.
|
|
56
82
|
|
|
83
|
+
## Useful Canvas Sets
|
|
84
|
+
|
|
85
|
+
Translate the user's requested review into the smallest useful set of frames:
|
|
86
|
+
|
|
87
|
+
- **Multi-step flow:** one ordered frame per route or query state, such as cart,
|
|
88
|
+
shipping, payment, and confirmation.
|
|
89
|
+
- **Multiple pages:** one frame per meaningful route, such as home, pricing,
|
|
90
|
+
docs, and account settings.
|
|
91
|
+
- **Responsive comparison:** repeat the same route at the requested desktop,
|
|
92
|
+
tablet, and mobile viewports so they align in one row.
|
|
93
|
+
- **State review:** repeat a route for meaningful URL-addressable states such as
|
|
94
|
+
empty, loading, error, modal-open, or selected-item views.
|
|
95
|
+
|
|
96
|
+
Do not expand every discovered route or every viewport unless the user asks for
|
|
97
|
+
an exhaustive audit. Preserve the user's labels and sequence so the canvas reads
|
|
98
|
+
like the workflow they described.
|
|
99
|
+
|
|
57
100
|
## Select And Reprompt
|
|
58
101
|
|
|
59
102
|
When a chat message begins with `[Reprompt selection]`, the selected subtree is
|
|
@@ -275,9 +318,9 @@ Fallback, only when `open-visual-edit` is unavailable:
|
|
|
275
318
|
## Open The Design Surface
|
|
276
319
|
|
|
277
320
|
- Use the `link`, `deepLink`, or MCP App embed returned by Design actions so
|
|
278
|
-
the user sees the canvas.
|
|
279
|
-
|
|
280
|
-
|
|
321
|
+
the user sees the canvas. Follow **Put Design Beside The Chat**: prefer the
|
|
322
|
+
host's inline Browser, preview, or webview panel; otherwise surface the
|
|
323
|
+
**Open design** link.
|
|
281
324
|
- Return or open the `openUrl` / action link, not a hand-built
|
|
282
325
|
`/design/:id?_session=...` URL.
|
|
283
326
|
- If the user is working in VS Code, the Agent Native extension can open the
|
|
@@ -3177,17 +3177,19 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
3177
3177
|
// Cmd/Ctrl+R rename / Cmd/Ctrl+Shift+R paste-to-replace (onRename /
|
|
3178
3178
|
// onPasteToReplace) — both live under bare primary+r.
|
|
3179
3179
|
"r",
|
|
3180
|
-
// Cmd/Ctrl
|
|
3181
|
-
|
|
3180
|
+
// Cmd/Ctrl+K — open the host command menu even while the iframe has
|
|
3181
|
+
// focus. DesignEditor routes this chord to openCommandMenu().
|
|
3182
|
+
"k"
|
|
3182
3183
|
].indexOf(normalized) !== -1 || e.code === "Digit1" || e.code === "Digit2" || key === "1" || key === "2" || // Cmd/Ctrl+Shift+H / +L — toggle hidden / toggle locked
|
|
3183
3184
|
// (onToggleHidden / onToggleLocked). Gated on shiftKey so bare
|
|
3184
3185
|
// Cmd+H / Cmd+L — common OS "Hide app" / browser "focus address bar"
|
|
3185
3186
|
// shortcuts the host has no bare-primary binding for — are left
|
|
3186
3187
|
// alone (see useDesignHotkeys.ts: both require event.shiftKey).
|
|
3187
|
-
e.shiftKey && (normalized === "h" || normalized === "l") || // Cmd/Ctrl+
|
|
3188
|
+
e.shiftKey && (normalized === "h" || normalized === "l") || // Cmd/Ctrl+Shift+\\ — minimize UI (onToggleUi). Keep the Shift gate
|
|
3189
|
+
// here so the iframe never intercepts a desktop host's bare Cmd/Ctrl+\\.
|
|
3190
|
+
e.shiftKey && normalized === "\\\\" || // Cmd/Ctrl+Alt+B detach instance / Cmd/Ctrl+Alt+K create component
|
|
3188
3191
|
// (onDetachInstance / onCreateComponent). Gated on altKey so bare
|
|
3189
|
-
// Cmd+B
|
|
3190
|
-
// binding for either.
|
|
3192
|
+
// Cmd+B is left alone — the host has no bare-primary binding for it.
|
|
3191
3193
|
e.altKey && (normalized === "b" || normalized === "k") || // Ctrl+Alt+H / Ctrl+Alt+T — distribute horizontal / tidy up
|
|
3192
3194
|
// (onDistributeSelection / onTidyUp). useDesignHotkeys.ts keeps these
|
|
3193
3195
|
// on LITERAL Control on every platform (never remapped to Cmd), so
|
|
@@ -52,7 +52,7 @@ import type { CanvasLayerHitCandidate } from "./types";
|
|
|
52
52
|
// EMPTY canvas (no selection):
|
|
53
53
|
// Paste here
|
|
54
54
|
// [sep]
|
|
55
|
-
// Show/Hide UI
|
|
55
|
+
// Show/Hide UI ⇧⌘\ · Show/Hide comments ⇧C
|
|
56
56
|
//
|
|
57
57
|
// Real Figma has no Duplicate/Delete/Select-all/Zoom items on either canvas
|
|
58
58
|
// menu (all keyboard-only there) — those are intentionally NOT rendered here
|
|
@@ -461,7 +461,7 @@ const DEFAULT_SHORTCUTS: CanvasContextMenuShortcuts = {
|
|
|
461
461
|
rotateClockwise: "",
|
|
462
462
|
flipHorizontal: "⇧H",
|
|
463
463
|
flipVertical: "⇧V",
|
|
464
|
-
toggleUi: "
|
|
464
|
+
toggleUi: "⇧⌘\\",
|
|
465
465
|
toggleComments: "⇧C",
|
|
466
466
|
};
|
|
467
467
|
|
|
@@ -4672,8 +4672,9 @@ declare var __SELECTED_LAYER_DRAG_PRIORITY__: boolean;
|
|
|
4672
4672
|
// Cmd/Ctrl+R rename / Cmd/Ctrl+Shift+R paste-to-replace (onRename /
|
|
4673
4673
|
// onPasteToReplace) — both live under bare primary+r.
|
|
4674
4674
|
"r",
|
|
4675
|
-
// Cmd/Ctrl
|
|
4676
|
-
|
|
4675
|
+
// Cmd/Ctrl+K — open the host command menu even while the iframe has
|
|
4676
|
+
// focus. DesignEditor routes this chord to openCommandMenu().
|
|
4677
|
+
"k",
|
|
4677
4678
|
].indexOf(normalized) !== -1 ||
|
|
4678
4679
|
e.code === "Digit1" ||
|
|
4679
4680
|
e.code === "Digit2" ||
|
|
@@ -4685,10 +4686,12 @@ declare var __SELECTED_LAYER_DRAG_PRIORITY__: boolean;
|
|
|
4685
4686
|
// shortcuts the host has no bare-primary binding for — are left
|
|
4686
4687
|
// alone (see useDesignHotkeys.ts: both require event.shiftKey).
|
|
4687
4688
|
(e.shiftKey && (normalized === "h" || normalized === "l")) ||
|
|
4689
|
+
// Cmd/Ctrl+Shift+\ — minimize UI (onToggleUi). Keep the Shift gate
|
|
4690
|
+
// here so the iframe never intercepts a desktop host's bare Cmd/Ctrl+\.
|
|
4691
|
+
(e.shiftKey && normalized === "\\") ||
|
|
4688
4692
|
// Cmd/Ctrl+Alt+B detach instance / Cmd/Ctrl+Alt+K create component
|
|
4689
4693
|
// (onDetachInstance / onCreateComponent). Gated on altKey so bare
|
|
4690
|
-
// Cmd+B
|
|
4691
|
-
// binding for either.
|
|
4694
|
+
// Cmd+B is left alone — the host has no bare-primary binding for it.
|
|
4692
4695
|
(e.altKey && (normalized === "b" || normalized === "k")) ||
|
|
4693
4696
|
// Ctrl+Alt+H / Ctrl+Alt+T — distribute horizontal / tidy up
|
|
4694
4697
|
// (onDistributeSelection / onTidyUp). useDesignHotkeys.ts keeps these
|
|
@@ -142,7 +142,7 @@ export const DESIGN_SHORTCUTS: readonly DesignShortcutDefinition[] = [
|
|
|
142
142
|
shortcut({
|
|
143
143
|
id: "toggle-ui",
|
|
144
144
|
category: "view",
|
|
145
|
-
bindings: ["$mod+\\"],
|
|
145
|
+
bindings: ["$mod+shift+\\"],
|
|
146
146
|
labelKey: "designEditor.keyboardShortcuts.commands.toggleUi",
|
|
147
147
|
handler: "onToggleUi",
|
|
148
148
|
}),
|
|
@@ -203,8 +203,8 @@ export interface UseDesignHotkeysProps {
|
|
|
203
203
|
* modifiers held) or SHIFT_TOOL_SHORTCUTS (which has no "a" entry).
|
|
204
204
|
*/
|
|
205
205
|
onAddAutoLayout?: DesignHotkeyHandler;
|
|
206
|
-
/** Figma's Cmd+\
|
|
207
|
-
*
|
|
206
|
+
/** Figma's Cmd/Ctrl+Shift+\ "Minimize UI" shortcut, applied here to the
|
|
207
|
+
* full Design chrome (left rail, right panel, and bottom toolbar). */
|
|
208
208
|
onToggleUi?: DesignHotkeyHandler;
|
|
209
209
|
/** Figma's Shift+C — toggle Show/Hide comments (comment pins). */
|
|
210
210
|
onToggleComments?: DesignHotkeyHandler;
|
|
@@ -725,8 +725,14 @@ export function handleDesignHotkey(
|
|
|
725
725
|
return run(props.onAddAutoLayout);
|
|
726
726
|
}
|
|
727
727
|
|
|
728
|
-
// Figma
|
|
729
|
-
|
|
728
|
+
// Figma's "Minimize UI" chord avoids the bare Cmd+\ shortcut that desktop
|
|
729
|
+
// coding hosts can reserve for closing their focused pane.
|
|
730
|
+
if (
|
|
731
|
+
isPlatformPrimaryModifier(event) &&
|
|
732
|
+
!event.altKey &&
|
|
733
|
+
event.shiftKey &&
|
|
734
|
+
key === "\\"
|
|
735
|
+
) {
|
|
730
736
|
return run(props.onToggleUi);
|
|
731
737
|
}
|
|
732
738
|
|
|
@@ -13,7 +13,12 @@ import {
|
|
|
13
13
|
useCommandMenuShortcut,
|
|
14
14
|
} from "@agent-native/core/client/navigation";
|
|
15
15
|
import { getThemeInitScript } from "@agent-native/core/client/ui";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
IconArrowsMaximize,
|
|
18
|
+
IconHierarchy2,
|
|
19
|
+
IconSun,
|
|
20
|
+
IconMoon,
|
|
21
|
+
} from "@tabler/icons-react";
|
|
17
22
|
import { useQueryClient } from "@tanstack/react-query";
|
|
18
23
|
import { useTheme } from "next-themes";
|
|
19
24
|
import { useCallback, useState } from "react";
|
|
@@ -31,6 +36,7 @@ import type { LinksFunction } from "react-router";
|
|
|
31
36
|
import { Layout as AppLayout } from "@/components/layout/Layout";
|
|
32
37
|
import { Toaster } from "@/components/ui/sonner";
|
|
33
38
|
import { AppToolkitProvider } from "@/components/ui/toolkit-provider";
|
|
39
|
+
import { requestDesignUiToggle } from "@/lib/design-ui-events";
|
|
34
40
|
|
|
35
41
|
import changelog from "../CHANGELOG.md?raw";
|
|
36
42
|
import { i18nCatalog } from "./i18n";
|
|
@@ -128,7 +134,9 @@ function DesignCommandMenu({
|
|
|
128
134
|
onOpenChange: (open: boolean) => void;
|
|
129
135
|
}) {
|
|
130
136
|
const t = useT();
|
|
137
|
+
const location = useLocation();
|
|
131
138
|
const navigate = useNavigate();
|
|
139
|
+
const isDesignEditor = location.pathname.startsWith("/design/");
|
|
132
140
|
return (
|
|
133
141
|
<CommandMenu
|
|
134
142
|
open={open}
|
|
@@ -146,6 +154,15 @@ function DesignCommandMenu({
|
|
|
146
154
|
</CommandMenu.Item>
|
|
147
155
|
</CommandMenu.Group>
|
|
148
156
|
<CommandMenu.Group heading={t("root.commandAppearance")}>
|
|
157
|
+
{isDesignEditor ? (
|
|
158
|
+
<CommandMenu.Item
|
|
159
|
+
onSelect={requestDesignUiToggle}
|
|
160
|
+
keywords={["canvas", "focus", "panels", "hide ui", "show ui"]}
|
|
161
|
+
>
|
|
162
|
+
<IconArrowsMaximize size={16} />
|
|
163
|
+
{t("designEditor.keyboardShortcuts.commands.toggleUi")}
|
|
164
|
+
</CommandMenu.Item>
|
|
165
|
+
) : null}
|
|
149
166
|
<ThemeToggleItem />
|
|
150
167
|
</CommandMenu.Group>
|
|
151
168
|
</CommandMenu>
|
|
@@ -305,6 +305,38 @@ export default defineAction({
|
|
|
305
305
|
|
|
306
306
|
On success the validated value is returned, so coercion/defaults on `outputSchema` apply. Omit `outputSchema` and behavior is byte-for-byte unchanged (no wrapping).
|
|
307
307
|
|
|
308
|
+
### Authorization (`authorize`)
|
|
309
|
+
|
|
310
|
+
`authorize` decides whether the caller may run the action at all. It wraps
|
|
311
|
+
`run`, so it holds at **all six dispatch sites** — agent tool, HTTP, frontend
|
|
312
|
+
hook, MCP, A2A, CLI — unlike `needsApproval`, which is honoured only in the
|
|
313
|
+
agent loop. Use `authorize` for "not everyone may do this"; use `needsApproval`
|
|
314
|
+
to ask a human to bless one call a permitted caller is already allowed to make.
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
import { coachAccess } from "../lib/access.js"; // defineAppRoles(...)
|
|
318
|
+
|
|
319
|
+
export default defineAction({
|
|
320
|
+
description: "Archive a client roster.",
|
|
321
|
+
schema: z.object({ id: z.string() }),
|
|
322
|
+
authorize: coachAccess.requireAny("coach-admin"),
|
|
323
|
+
run: async (args) => {
|
|
324
|
+
/* ... */
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
The wrappers compose as `validate input -> authorize -> run -> validate output
|
|
330
|
+
-> audit`: the gate sits inside input validation, so a guard reading `args` gets
|
|
331
|
+
the parsed, coerced value, and auditing is outermost, so denials are recorded.
|
|
332
|
+
|
|
333
|
+
A guard that throws denies with its own message; returning `false` denies
|
|
334
|
+
generically; anything else (including `undefined`) allows. A guarded action
|
|
335
|
+
needs a user identity, so an unattended CLI/cron caller with no user email is
|
|
336
|
+
denied. `authorize` gates the operation; `accessFilter` / `assertAccess` still
|
|
337
|
+
scope which rows a permitted caller may touch. See the `authentication` skill
|
|
338
|
+
for `defineAppRoles` and the `sharing` skill for row scoping.
|
|
339
|
+
|
|
308
340
|
### Human-in-the-Loop Approval (`needsApproval`)
|
|
309
341
|
|
|
310
342
|
For high-consequence, outward-facing, hard-to-undo actions (sending an email, charging a card, deleting an account), set `needsApproval` so the agent **cannot** run the action without a human approving the specific call:
|
|
@@ -159,6 +159,35 @@ whole site. Data scoping lives in actions and API routes; the client gates
|
|
|
159
159
|
private UI after the shell loads. See the `authentication` skill and
|
|
160
160
|
`guard:ssr-cache-shell` / `ssr-handler.spec.ts`.
|
|
161
161
|
|
|
162
|
+
**Authorization beyond "is there a session" — `authorize`.** The auth guard only
|
|
163
|
+
proves *someone* is signed in. To restrict an operation to some teammates, set
|
|
164
|
+
`authorize` on the `defineAction`. It wraps `run`, so it applies at every
|
|
165
|
+
dispatch site (agent tool, HTTP, frontend, MCP, A2A, CLI) — unlike
|
|
166
|
+
`needsApproval`, which is honoured only in the agent loop.
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { coachAccess } from "../lib/access.js"; // defineAppRoles(...)
|
|
170
|
+
|
|
171
|
+
export default defineAction({
|
|
172
|
+
description: "Archive a client roster.",
|
|
173
|
+
schema: z.object({ id: z.string() }),
|
|
174
|
+
authorize: coachAccess.requireAny("coach-admin"),
|
|
175
|
+
run: async (args) => {
|
|
176
|
+
/* ... */
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
A guard that throws denies with its own message; returning `false` denies
|
|
182
|
+
generically; anything else (including `undefined`) allows. Guarded actions need
|
|
183
|
+
a user identity — an unattended CLI/cron caller with no user email is denied.
|
|
184
|
+
|
|
185
|
+
`authorize` is **not** a substitute for `accessFilter` / `assertAccess`. It
|
|
186
|
+
decides whether this caller may perform the operation at all; `accessFilter` /
|
|
187
|
+
`assertAccess` scope which rows a permitted caller may see or touch. A
|
|
188
|
+
restricted write action needs both. See the `authentication` skill for
|
|
189
|
+
`defineAppRoles` and the `actions` skill for the full surface.
|
|
190
|
+
|
|
162
191
|
## Human-in-the-Loop Approval for High-Consequence Actions
|
|
163
192
|
|
|
164
193
|
For a small set of outward-facing, hard-to-undo operations — sending an email, charging a card, deleting an account, posting publicly — auth and access control are necessary but not sufficient: you also do not want the **agent** to perform them autonomously. Set `needsApproval` on the `defineAction` so the agent cannot run the action without a human approving the specific call.
|
|
@@ -274,6 +303,8 @@ Run `pnpm action db-check-scoping` to verify. Use `--require-org` for multi-org
|
|
|
274
303
|
- [ ] New env vars in `.env` only, not committed
|
|
275
304
|
- [ ] New user-data tables have `owner_email` column
|
|
276
305
|
- [ ] Custom routes call `getSession` and reject unauthenticated requests
|
|
306
|
+
- [ ] Actions only some teammates may run set `authorize` (in addition to any
|
|
307
|
+
`accessFilter` / `assertAccess` row scoping)
|
|
277
308
|
|
|
278
309
|
## Related Skills
|
|
279
310
|
|
|
@@ -34,6 +34,8 @@ Visibility is coarse. Explicit share grants are fine-grained (per user or per or
|
|
|
34
34
|
- **`editor`** — read + write.
|
|
35
35
|
- **`admin`** — read + write + manage shares. Does NOT replace the single `owner_email` on the resource.
|
|
36
36
|
|
|
37
|
+
There are three role systems and they never imply one another. A share role answers "what may this person do to **one row**". An org role (`org_members.role`) answers "what may this person do to the **team**". An app role (`defineAppRoles`, see the `authentication` skill) answers "what may this person do inside **one app**". A share `admin` is not an app admin and neither is an org admin.
|
|
38
|
+
|
|
37
39
|
### Anonymous public URLs stay separate
|
|
38
40
|
|
|
39
41
|
Form "publish" slugs, booking-link slugs, any feature that exposes a URL to unauthenticated users — these are a different axis and are NOT controlled by the sharing system. Keep them alongside it.
|
|
@@ -137,6 +139,8 @@ export default defineAction({
|
|
|
137
139
|
|
|
138
140
|
For delete actions use `"admin"` (or fold in `"owner"` to require the real owner).
|
|
139
141
|
|
|
142
|
+
`authorize` is a different axis, not an alternative: it gates whether the caller may run the operation at all, while `assertAccess` scopes which row they may touch. A write action restricted to some teammates needs both — `authorize: appAccess.requireAny(...)` on the action, `assertAccess` inside `run`.
|
|
143
|
+
|
|
140
144
|
## Create actions must set owner
|
|
141
145
|
|
|
142
146
|
When inserting a new row, fill `ownerEmail` and `orgId` from the request context:
|
|
@@ -305,6 +305,38 @@ export default defineAction({
|
|
|
305
305
|
|
|
306
306
|
On success the validated value is returned, so coercion/defaults on `outputSchema` apply. Omit `outputSchema` and behavior is byte-for-byte unchanged (no wrapping).
|
|
307
307
|
|
|
308
|
+
### Authorization (`authorize`)
|
|
309
|
+
|
|
310
|
+
`authorize` decides whether the caller may run the action at all. It wraps
|
|
311
|
+
`run`, so it holds at **all six dispatch sites** — agent tool, HTTP, frontend
|
|
312
|
+
hook, MCP, A2A, CLI — unlike `needsApproval`, which is honoured only in the
|
|
313
|
+
agent loop. Use `authorize` for "not everyone may do this"; use `needsApproval`
|
|
314
|
+
to ask a human to bless one call a permitted caller is already allowed to make.
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
import { coachAccess } from "../lib/access.js"; // defineAppRoles(...)
|
|
318
|
+
|
|
319
|
+
export default defineAction({
|
|
320
|
+
description: "Archive a client roster.",
|
|
321
|
+
schema: z.object({ id: z.string() }),
|
|
322
|
+
authorize: coachAccess.requireAny("coach-admin"),
|
|
323
|
+
run: async (args) => {
|
|
324
|
+
/* ... */
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
The wrappers compose as `validate input -> authorize -> run -> validate output
|
|
330
|
+
-> audit`: the gate sits inside input validation, so a guard reading `args` gets
|
|
331
|
+
the parsed, coerced value, and auditing is outermost, so denials are recorded.
|
|
332
|
+
|
|
333
|
+
A guard that throws denies with its own message; returning `false` denies
|
|
334
|
+
generically; anything else (including `undefined`) allows. A guarded action
|
|
335
|
+
needs a user identity, so an unattended CLI/cron caller with no user email is
|
|
336
|
+
denied. `authorize` gates the operation; `accessFilter` / `assertAccess` still
|
|
337
|
+
scope which rows a permitted caller may touch. See the `authentication` skill
|
|
338
|
+
for `defineAppRoles` and the `sharing` skill for row scoping.
|
|
339
|
+
|
|
308
340
|
### Human-in-the-Loop Approval (`needsApproval`)
|
|
309
341
|
|
|
310
342
|
For high-consequence, outward-facing, hard-to-undo actions (sending an email, charging a card, deleting an account), set `needsApproval` so the agent **cannot** run the action without a human approving the specific call:
|
|
@@ -159,6 +159,35 @@ whole site. Data scoping lives in actions and API routes; the client gates
|
|
|
159
159
|
private UI after the shell loads. See the `authentication` skill and
|
|
160
160
|
`guard:ssr-cache-shell` / `ssr-handler.spec.ts`.
|
|
161
161
|
|
|
162
|
+
**Authorization beyond "is there a session" — `authorize`.** The auth guard only
|
|
163
|
+
proves *someone* is signed in. To restrict an operation to some teammates, set
|
|
164
|
+
`authorize` on the `defineAction`. It wraps `run`, so it applies at every
|
|
165
|
+
dispatch site (agent tool, HTTP, frontend, MCP, A2A, CLI) — unlike
|
|
166
|
+
`needsApproval`, which is honoured only in the agent loop.
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { coachAccess } from "../lib/access.js"; // defineAppRoles(...)
|
|
170
|
+
|
|
171
|
+
export default defineAction({
|
|
172
|
+
description: "Archive a client roster.",
|
|
173
|
+
schema: z.object({ id: z.string() }),
|
|
174
|
+
authorize: coachAccess.requireAny("coach-admin"),
|
|
175
|
+
run: async (args) => {
|
|
176
|
+
/* ... */
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
A guard that throws denies with its own message; returning `false` denies
|
|
182
|
+
generically; anything else (including `undefined`) allows. Guarded actions need
|
|
183
|
+
a user identity — an unattended CLI/cron caller with no user email is denied.
|
|
184
|
+
|
|
185
|
+
`authorize` is **not** a substitute for `accessFilter` / `assertAccess`. It
|
|
186
|
+
decides whether this caller may perform the operation at all; `accessFilter` /
|
|
187
|
+
`assertAccess` scope which rows a permitted caller may see or touch. A
|
|
188
|
+
restricted write action needs both. See the `authentication` skill for
|
|
189
|
+
`defineAppRoles` and the `actions` skill for the full surface.
|
|
190
|
+
|
|
162
191
|
## Human-in-the-Loop Approval for High-Consequence Actions
|
|
163
192
|
|
|
164
193
|
For a small set of outward-facing, hard-to-undo operations — sending an email, charging a card, deleting an account, posting publicly — auth and access control are necessary but not sufficient: you also do not want the **agent** to perform them autonomously. Set `needsApproval` on the `defineAction` so the agent cannot run the action without a human approving the specific call.
|
|
@@ -274,6 +303,8 @@ Run `pnpm action db-check-scoping` to verify. Use `--require-org` for multi-org
|
|
|
274
303
|
- [ ] New env vars in `.env` only, not committed
|
|
275
304
|
- [ ] New user-data tables have `owner_email` column
|
|
276
305
|
- [ ] Custom routes call `getSession` and reject unauthenticated requests
|
|
306
|
+
- [ ] Actions only some teammates may run set `authorize` (in addition to any
|
|
307
|
+
`accessFilter` / `assertAccess` row scoping)
|
|
277
308
|
|
|
278
309
|
## Related Skills
|
|
279
310
|
|
|
@@ -34,6 +34,8 @@ Visibility is coarse. Explicit share grants are fine-grained (per user or per or
|
|
|
34
34
|
- **`editor`** — read + write.
|
|
35
35
|
- **`admin`** — read + write + manage shares. Does NOT replace the single `owner_email` on the resource.
|
|
36
36
|
|
|
37
|
+
There are three role systems and they never imply one another. A share role answers "what may this person do to **one row**". An org role (`org_members.role`) answers "what may this person do to the **team**". An app role (`defineAppRoles`, see the `authentication` skill) answers "what may this person do inside **one app**". A share `admin` is not an app admin and neither is an org admin.
|
|
38
|
+
|
|
37
39
|
### Anonymous public URLs stay separate
|
|
38
40
|
|
|
39
41
|
Form "publish" slugs, booking-link slugs, any feature that exposes a URL to unauthenticated users — these are a different axis and are NOT controlled by the sharing system. Keep them alongside it.
|
|
@@ -137,6 +139,8 @@ export default defineAction({
|
|
|
137
139
|
|
|
138
140
|
For delete actions use `"admin"` (or fold in `"owner"` to require the real owner).
|
|
139
141
|
|
|
142
|
+
`authorize` is a different axis, not an alternative: it gates whether the caller may run the operation at all, while `assertAccess` scopes which row they may touch. A write action restricted to some teammates needs both — `authorize: appAccess.requireAny(...)` on the action, `assertAccess` inside `run`.
|
|
143
|
+
|
|
140
144
|
## Create actions must set owner
|
|
141
145
|
|
|
142
146
|
When inserting a new row, fill `ownerEmail` and `orgId` from the request context:
|