@agent-native/core 0.162.0 → 0.163.1

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.
Files changed (132) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +27 -2
  3. package/corpus/templates/analytics/server/plugins/collab.ts +1 -0
  4. package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +27 -2
  5. package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +27 -2
  6. package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +27 -2
  7. package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +27 -2
  8. package/corpus/templates/clips/app/lib/camera-composite.ts +15 -1
  9. package/corpus/templates/clips/changelog/2026-08-18-clips-no-longer-crashes-when-a-camera-bubble-starts-at-a-tin.md +6 -0
  10. package/corpus/templates/content/.agents/skills/sharing/SKILL.md +27 -2
  11. package/corpus/templates/content/actions/create-content-database.ts +1 -1
  12. package/corpus/templates/content/actions/create-document.ts +1 -1
  13. package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +27 -2
  14. package/corpus/templates/design/.agents/skills/sharing/SKILL.md +27 -2
  15. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +6 -1
  16. package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +27 -2
  17. package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +27 -2
  18. package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +27 -2
  19. package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +27 -2
  20. package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +27 -2
  21. package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +27 -2
  22. package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +27 -2
  23. package/corpus/templates/slides/DEVELOPING.md +17 -0
  24. package/corpus/templates/slides/actions/get-deck-access-status.ts +67 -0
  25. package/corpus/templates/slides/actions/request-deck-access.ts +569 -0
  26. package/corpus/templates/slides/agent-native.json +3 -0
  27. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +3 -3
  28. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +3 -3
  29. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +3 -1
  30. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +1 -1
  31. package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +1 -1
  32. package/corpus/templates/slides/app/components/layout/Header.tsx +2 -0
  33. package/corpus/templates/slides/app/hooks/use-deck-access.ts +51 -0
  34. package/corpus/templates/slides/app/i18n/en-US.ts +12 -0
  35. package/corpus/templates/slides/app/lib/deck-editor-loading.ts +7 -0
  36. package/corpus/templates/slides/app/pages/DeckEditor.tsx +173 -33
  37. package/corpus/templates/slides/changelog/2026-08-18-private-deck-links-now-explain-access-and-let-viewers-notify.md +6 -0
  38. package/corpus/templates/slides/server/db/schema.ts +10 -0
  39. package/corpus/templates/slides/server/handlers/request-auth-context.ts +1 -0
  40. package/corpus/templates/slides/server/plugins/db.ts +17 -0
  41. package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +27 -2
  42. package/dist/app-config/schema.d.ts +1 -0
  43. package/dist/app-config/workspace.d.ts +1 -0
  44. package/dist/app-config/workspace.js +8 -0
  45. package/dist/chat-threads/schema.d.ts +2 -2
  46. package/dist/client/analytics.d.ts +1 -0
  47. package/dist/client/analytics.js +19 -5
  48. package/dist/client/org/TeamPage.js +15 -2
  49. package/dist/client/org/hooks.d.ts +2 -0
  50. package/dist/client/org/hooks.js +12 -0
  51. package/dist/client/org/index.d.ts +2 -2
  52. package/dist/client/org/index.js +1 -1
  53. package/dist/client/sharing/ShareButton.js +43 -18
  54. package/dist/client/sharing/useShareButtonController.d.ts +12 -2
  55. package/dist/client/sharing/useShareButtonController.js +38 -8
  56. package/dist/collab/awareness.d.ts +2 -2
  57. package/dist/collab/routes.d.ts +1 -1
  58. package/dist/collab/storage.d.ts +2 -0
  59. package/dist/collab/storage.js +7 -0
  60. package/dist/config.js +11 -1
  61. package/dist/dashboard-storage/schema.d.ts +2 -2
  62. package/dist/data-programs/schema.d.ts +2 -2
  63. package/dist/deploy/build.d.ts +1 -1
  64. package/dist/deploy/build.js +89 -12
  65. package/dist/extensions/schema.d.ts +2 -2
  66. package/dist/extensions/store.js +3 -0
  67. package/dist/localization/core-messages/ar-SA.js +1 -0
  68. package/dist/localization/core-messages/de-DE.js +1 -0
  69. package/dist/localization/core-messages/en-US.d.ts +1 -0
  70. package/dist/localization/core-messages/en-US.js +1 -0
  71. package/dist/localization/core-messages/es-ES.js +1 -0
  72. package/dist/localization/core-messages/fr-FR.js +1 -0
  73. package/dist/localization/core-messages/hi-IN.js +1 -0
  74. package/dist/localization/core-messages/ja-JP.js +1 -0
  75. package/dist/localization/core-messages/ko-KR.js +1 -0
  76. package/dist/localization/core-messages/pt-BR.js +1 -0
  77. package/dist/localization/core-messages/zh-CN.js +1 -0
  78. package/dist/localization/core-messages/zh-TW.js +1 -0
  79. package/dist/localization/core-messages.d.ts +1 -0
  80. package/dist/localization/default-messages.d.ts +4 -0
  81. package/dist/localization/default-messages.js +4 -0
  82. package/dist/observability/routes.d.ts +1 -1
  83. package/dist/observability/tracking-identity.js +2 -0
  84. package/dist/org/handlers.d.ts +6 -1
  85. package/dist/org/handlers.js +43 -0
  86. package/dist/org/index.d.ts +3 -3
  87. package/dist/org/index.js +2 -2
  88. package/dist/org/migrations.js +33 -0
  89. package/dist/org/plugin.js +10 -1
  90. package/dist/org/schema.d.ts +315 -0
  91. package/dist/org/schema.js +20 -1
  92. package/dist/org/types.d.ts +3 -0
  93. package/dist/org/workspace-app-access.d.ts +10 -0
  94. package/dist/org/workspace-app-access.js +179 -0
  95. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  96. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  97. package/dist/secrets/routes.d.ts +9 -9
  98. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  99. package/dist/server/auth.js +14 -1
  100. package/dist/server/collab-plugin.d.ts +6 -0
  101. package/dist/server/collab-plugin.js +27 -6
  102. package/dist/server/deploy-environment.d.ts +1 -1
  103. package/dist/server/deploy-environment.js +40 -2
  104. package/dist/server/poll.js +6 -0
  105. package/dist/server/realtime-token.d.ts +1 -1
  106. package/dist/server/sentry-config.js +8 -4
  107. package/dist/server/sentry.js +4 -0
  108. package/dist/sharing/access.d.ts +2 -2
  109. package/dist/sharing/access.js +56 -3
  110. package/dist/sharing/actions/list-resource-shares.d.ts +2 -0
  111. package/dist/sharing/actions/list-resource-shares.js +26 -1
  112. package/dist/sharing/actions/share-resource.d.ts +1 -1
  113. package/dist/sharing/actions/share-resource.js +23 -4
  114. package/dist/sharing/actions/unshare-resource.d.ts +1 -1
  115. package/dist/sharing/actions/unshare-resource.js +1 -1
  116. package/dist/sharing/registry.d.ts +12 -0
  117. package/dist/sharing/schema.d.ts +4 -4
  118. package/dist/sharing/schema.js +2 -2
  119. package/dist/templates/chat/.agents/skills/sharing/SKILL.md +27 -2
  120. package/dist/templates/default/.agents/skills/sharing/SKILL.md +27 -2
  121. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +27 -2
  122. package/dist/tracking/registry.js +8 -6
  123. package/dist/vite/client.js +5 -0
  124. package/dist/workspace-connections/actions/list-workspace-user-groups.d.ts +9 -1
  125. package/dist/workspace-connections/actions/list-workspace-user-groups.js +9 -4
  126. package/dist/workspace-connections/groups.d.ts +2 -0
  127. package/dist/workspace-connections/groups.js +16 -5
  128. package/docs/content/deployment.mdx +19 -5
  129. package/package.json +1 -1
  130. package/src/templates/chat/.agents/skills/sharing/SKILL.md +27 -2
  131. package/src/templates/default/.agents/skills/sharing/SKILL.md +27 -2
  132. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +27 -2
@@ -891,6 +891,77 @@ function isTruthyRuntimeValue(value) {
891
891
  );
892
892
  }
893
893
 
894
+ function normalizeExplicitDeploymentEnvironment(value) {
895
+ const normalized = firstNonEmpty(value)?.toLowerCase();
896
+ if (!normalized) return;
897
+ if (
898
+ normalized !== "local" &&
899
+ normalized !== "beta" &&
900
+ normalized !== "production" &&
901
+ normalized !== "preview"
902
+ ) {
903
+ throw new Error(
904
+ 'AGENT_NATIVE_DEPLOYMENT_ENVIRONMENT must be "local", "beta", "production", or "preview"',
905
+ );
906
+ }
907
+ return normalized;
908
+ }
909
+
910
+ function normalizeFallbackDeploymentEnvironment(value) {
911
+ const normalized = firstNonEmpty(value)?.toLowerCase();
912
+ if (normalized === "development" || normalized === "test") return "local";
913
+ return normalized === "local" ||
914
+ normalized === "beta" ||
915
+ normalized === "production" ||
916
+ normalized === "preview"
917
+ ? normalized
918
+ : undefined;
919
+ }
920
+
921
+ function resolveDeploymentEnvironment() {
922
+ const env = globalThis.process?.env || {};
923
+ const explicit = normalizeExplicitDeploymentEnvironment(
924
+ env.AGENT_NATIVE_DEPLOYMENT_ENVIRONMENT,
925
+ );
926
+ if (explicit) return explicit;
927
+
928
+ const context = firstNonEmpty(
929
+ typeof env.CONTEXT === "string" ? env.CONTEXT : undefined,
930
+ typeof env.NETLIFY_CONTEXT === "string" ? env.NETLIFY_CONTEXT : undefined,
931
+ typeof env.AGENT_NATIVE_BUILD_DEPLOY_CONTEXT === "string"
932
+ ? env.AGENT_NATIVE_BUILD_DEPLOY_CONTEXT
933
+ : undefined,
934
+ )?.toLowerCase();
935
+ const branch =
936
+ typeof env.BRANCH === "string" ? env.BRANCH.trim().toLowerCase() : "";
937
+ const vercelEnv = String(env.VERCEL_ENV || "").trim().toLowerCase();
938
+ const sentryEnvironment = firstNonEmpty(env.SENTRY_ENVIRONMENT);
939
+ if (branch === "beta") return "beta";
940
+ if (
941
+ branch === "production" ||
942
+ (context === "production" && branch !== "beta")
943
+ ) {
944
+ return "production";
945
+ }
946
+ if (context === "branch-deploy" && branch === "main") return "beta";
947
+ if (
948
+ context === "deploy-preview" ||
949
+ context === "branch-deploy" ||
950
+ branch.startsWith("deploy-preview") ||
951
+ vercelEnv === "preview"
952
+ ) {
953
+ return "preview";
954
+ }
955
+ if (!context && !branch && !vercelEnv && sentryEnvironment) {
956
+ return normalizeFallbackDeploymentEnvironment(sentryEnvironment) || "production";
957
+ }
958
+ return (
959
+ normalizeFallbackDeploymentEnvironment(firstNonEmpty(context, vercelEnv)) ||
960
+ normalizeFallbackDeploymentEnvironment(env.NODE_ENV) ||
961
+ "production"
962
+ );
963
+ }
964
+
894
965
  function getSentryClientConfigScript() {
895
966
  const env = globalThis.process?.env || {};
896
967
  const key = firstNonEmpty(env.SENTRY_CLIENT_KEY, env.VITE_SENTRY_CLIENT_KEY);
@@ -909,16 +980,15 @@ function getSentryClientConfigScript() {
909
980
  env.VITE_SENTRY_DSN,
910
981
  env.SENTRY_DSN,
911
982
  ) || (key && projectId && host ? "https://" + key + "@" + host + "/" + projectId : undefined);
912
- if (!dsn) return null;
983
+ const deploymentEnvironment = resolveDeploymentEnvironment();
913
984
  const config = {
914
- sentryDsn: dsn,
915
- sentryEnvironment:
916
- firstNonEmpty(
917
- env.SENTRY_ENVIRONMENT,
918
- env.NETLIFY_CONTEXT,
919
- env.VERCEL_ENV,
920
- env.NODE_ENV,
921
- ) || "production",
985
+ ...(dsn
986
+ ? {
987
+ sentryDsn: dsn,
988
+ sentryEnvironment: deploymentEnvironment,
989
+ }
990
+ : {}),
991
+ deploymentEnvironment,
922
992
  };
923
993
  return (
924
994
  '<script data-agent-native-sentry-config>' +
@@ -3742,7 +3812,9 @@ function createBrowserOnlyServerStubPlugin() {
3742
3812
  },
3743
3813
  };
3744
3814
  }
3745
- export function resolveNitroBuildReplacements(env = process.env) {
3815
+ export function resolveNitroBuildReplacements(env = process.env, deploymentEnvironment) {
3816
+ const configuredDeploymentEnvironment = deploymentEnvironment?.trim() ||
3817
+ env.AGENT_NATIVE_DEPLOYMENT_ENVIRONMENT?.trim();
3746
3818
  return {
3747
3819
  // Netlify exposes DEPLOY_ID only while building. Embed it into the Nitro
3748
3820
  // function so preview OAuth relays can target this immutable deployment
@@ -3755,7 +3827,12 @@ export function resolveNitroBuildReplacements(env = process.env) {
3755
3827
  // a separate server build, so embed release migration ownership here as
3756
3828
  // well as in the Vite server bundle.
3757
3829
  "process.env.AGENT_NATIVE_RELEASE_MIGRATIONS": JSON.stringify(env.AGENT_NATIVE_RELEASE_MIGRATIONS?.trim() || ""),
3758
- "process.env.AGENT_NATIVE_BUILD_DEPLOY_CONTEXT": JSON.stringify(env.CONTEXT?.trim() || ""),
3830
+ "process.env.AGENT_NATIVE_BUILD_DEPLOY_CONTEXT": JSON.stringify(env.CONTEXT?.trim() || env.NETLIFY_CONTEXT?.trim() || ""),
3831
+ ...(configuredDeploymentEnvironment
3832
+ ? {
3833
+ "process.env.AGENT_NATIVE_DEPLOYMENT_ENVIRONMENT": JSON.stringify(configuredDeploymentEnvironment),
3834
+ }
3835
+ : {}),
3759
3836
  };
3760
3837
  }
3761
3838
  async function buildWithNitro() {
@@ -3841,7 +3918,7 @@ export default bundle;
3841
3918
  virtual: {
3842
3919
  "virtual:agents-bundle": agentsBundleModuleSource,
3843
3920
  },
3844
- replace: resolveNitroBuildReplacements(),
3921
+ replace: resolveNitroBuildReplacements(process.env, nitroAgentConfig.deployment?.environment),
3845
3922
  // Replace browser-only renderers (Excalidraw/Mermaid) with an inert proxy in
3846
3923
  // the server bundle. Without this, Nitro's Rolldown build pulls the real
3847
3924
  // Excalidraw into a shared vendor chunk imported statically by the SSR render
@@ -316,14 +316,14 @@ export declare const extensionShares: import("drizzle-orm/sqlite-core").SQLiteTa
316
316
  tableName: string;
317
317
  dataType: "string";
318
318
  columnType: "SQLiteText";
319
- data: "org" | "user";
319
+ data: "group" | "org" | "user";
320
320
  driverParam: string;
321
321
  notNull: true;
322
322
  hasDefault: false;
323
323
  isPrimaryKey: false;
324
324
  isAutoincrement: false;
325
325
  hasRuntimeDefault: false;
326
- enumValues: ["user", "org"];
326
+ enumValues: ["user", "group", "org"];
327
327
  baseColumn: never;
328
328
  identity: undefined;
329
329
  generated: undefined;
@@ -244,6 +244,9 @@ async function extensionChangeTargetsForRow(row) {
244
244
  else if (share.principalType === "org") {
245
245
  addExtensionChangeTarget(targets, { orgId: share.principalId });
246
246
  }
247
+ else if (share.principalType === "group" && row.orgId) {
248
+ addExtensionChangeTarget(targets, { orgId: row.orgId });
249
+ }
247
250
  }
248
251
  return Array.from(targets.values());
249
252
  }
@@ -486,6 +486,7 @@ const messages = {
486
486
  "share.unknownPerson": "شخص غير معروف",
487
487
  "share.viewer": "مشاهد",
488
488
  "share.viewerDescription": "يمكنه العرض",
489
+ "share.userGroup": "مجموعة مستخدمين",
489
490
  "status.resuming": "جارٍ الاستئناف",
490
491
  "status.stillWorking": "لا يزال قيد العمل",
491
492
  "status.thinking": "يفكّر",
@@ -521,5 +521,6 @@ const messages = {
521
521
  "share.unknownPerson": "Unbekannte Person",
522
522
  "share.viewer": "Betrachter",
523
523
  "share.viewerDescription": "Kann ansehen",
524
+ "share.userGroup": "Benutzergruppe",
524
525
  };
525
526
  export default messages;
@@ -470,6 +470,7 @@ declare const messages: {
470
470
  readonly "share.unknownPerson": "Unknown person";
471
471
  readonly "share.viewer": "Viewer";
472
472
  readonly "share.viewerDescription": "Can view";
473
+ readonly "share.userGroup": "User group";
473
474
  readonly "status.resuming": "Resuming";
474
475
  readonly "status.stillWorking": "Still working";
475
476
  readonly "status.thinking": "Thinking";
@@ -470,6 +470,7 @@ const messages = {
470
470
  "share.unknownPerson": "Unknown person",
471
471
  "share.viewer": "Viewer",
472
472
  "share.viewerDescription": "Can view",
473
+ "share.userGroup": "User group",
473
474
  "status.resuming": "Resuming",
474
475
  "status.stillWorking": "Still working",
475
476
  "status.thinking": "Thinking",
@@ -528,5 +528,6 @@ const messages = {
528
528
  "share.unknownPerson": "Persona desconocida",
529
529
  "share.viewer": "Lector",
530
530
  "share.viewerDescription": "Puede ver",
531
+ "share.userGroup": "Grupo de usuarios",
531
532
  };
532
533
  export default messages;
@@ -528,5 +528,6 @@ const messages = {
528
528
  "share.unknownPerson": "Personne inconnue",
529
529
  "share.viewer": "Lecteur",
530
530
  "share.viewerDescription": "Peut consulter",
531
+ "share.userGroup": "Groupe d’utilisateurs",
531
532
  };
532
533
  export default messages;
@@ -470,6 +470,7 @@ const messages = {
470
470
  "share.unknownPerson": "अज्ञात व्यक्ति",
471
471
  "share.viewer": "दर्शक",
472
472
  "share.viewerDescription": "देख सकता है",
473
+ "share.userGroup": "उपयोगकर्ता समूह",
473
474
  "status.resuming": "फिर से शुरू हो रहा है",
474
475
  "status.stillWorking": "अभी काम जारी है",
475
476
  "status.thinking": "सोच रहा है",
@@ -466,6 +466,7 @@ const messages = {
466
466
  "share.unknownPerson": "不明なユーザー",
467
467
  "share.viewer": "閲覧者",
468
468
  "share.viewerDescription": "閲覧可能",
469
+ "share.userGroup": "ユーザーグループ",
469
470
  "status.resuming": "再開中",
470
471
  "status.stillWorking": "処理を続けています",
471
472
  "status.thinking": "思考中",
@@ -466,6 +466,7 @@ const messages = {
466
466
  "share.unknownPerson": "알 수 없는 사용자",
467
467
  "share.viewer": "뷰어",
468
468
  "share.viewerDescription": "보기 가능",
469
+ "share.userGroup": "사용자 그룹",
469
470
  "status.resuming": "재개 중",
470
471
  "status.stillWorking": "계속 작업 중",
471
472
  "status.thinking": "생각 중",
@@ -528,5 +528,6 @@ const messages = {
528
528
  "share.unknownPerson": "Pessoa desconhecida",
529
529
  "share.viewer": "Visualizador",
530
530
  "share.viewerDescription": "Pode visualizar",
531
+ "share.userGroup": "Grupo de usuários",
531
532
  };
532
533
  export default messages;
@@ -466,6 +466,7 @@ const messages = {
466
466
  "share.unknownPerson": "未知人员",
467
467
  "share.viewer": "查看者",
468
468
  "share.viewerDescription": "可以查看",
469
+ "share.userGroup": "用户组",
469
470
  "status.resuming": "正在恢复",
470
471
  "status.stillWorking": "仍在处理",
471
472
  "status.thinking": "正在思考",
@@ -466,6 +466,7 @@ const messages = {
466
466
  "share.unknownPerson": "未知人員",
467
467
  "share.viewer": "檢視者",
468
468
  "share.viewerDescription": "可以檢視",
469
+ "share.userGroup": "使用者群組",
469
470
  "status.resuming": "正在繼續",
470
471
  "status.stillWorking": "仍在處理",
471
472
  "status.thinking": "正在思考",
@@ -472,6 +472,7 @@ export declare const englishAgentChatMessages: {
472
472
  readonly "share.unknownPerson": "Unknown person";
473
473
  readonly "share.viewer": "Viewer";
474
474
  readonly "share.viewerDescription": "Can view";
475
+ readonly "share.userGroup": "User group";
475
476
  readonly "status.resuming": "Resuming";
476
477
  readonly "status.stillWorking": "Still working";
477
478
  readonly "status.thinking": "Thinking";
@@ -879,6 +879,10 @@ declare const messages: {
879
879
  owner: string;
880
880
  admin: string;
881
881
  member: string;
882
+ workspaceAppsDefaultPrivacy: string;
883
+ workspaceAppsDefaultPrivacyDescription: string;
884
+ workspaceAppsOrganization: string;
885
+ workspaceAppsCreatorOnly: string;
882
886
  members: string;
883
887
  inviteMembers: string;
884
888
  invited: string;
@@ -885,6 +885,10 @@ const messages = {
885
885
  owner: "Owner",
886
886
  admin: "Admin",
887
887
  member: "Member",
888
+ workspaceAppsDefaultPrivacy: "New app privacy",
889
+ workspaceAppsDefaultPrivacyDescription: "Choose whether new workspace apps start private to their creator or visible to the organization.",
890
+ workspaceAppsOrganization: "Organization",
891
+ workspaceAppsCreatorOnly: "Creator only",
888
892
  members: "Members",
889
893
  inviteMembers: "Invite members",
890
894
  invited: "Invited",
@@ -62,6 +62,6 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
62
62
  summary?: undefined;
63
63
  spans?: undefined;
64
64
  id?: undefined;
65
- ok: boolean;
66
65
  error?: undefined;
66
+ ok: boolean;
67
67
  }>>;
@@ -1,3 +1,4 @@
1
+ import { resolveDeployEnvironment } from "../server/deploy-environment.js";
1
2
  function normalizeTrackingSlug(value) {
2
3
  const raw = value?.trim().toLowerCase();
3
4
  if (!raw)
@@ -44,6 +45,7 @@ export function trackingIdentityProperties() {
44
45
  normalizeTrackingSlug(process.env.VITE_APP_TEMPLATE) ||
45
46
  app;
46
47
  return {
48
+ deployment_environment: resolveDeployEnvironment(),
47
49
  ...(app ? { app, agent_native_app: app } : {}),
48
50
  ...(template ? { template, agent_native_template: template } : {}),
49
51
  };
@@ -1,4 +1,4 @@
1
- import type { OrgRole } from "./types.js";
1
+ import type { OrgRole, WorkspaceAppDefaultVisibility } from "./types.js";
2
2
  /** GET /_agent-native/org/me — current user's active org, all orgs, pending invitations */
3
3
  export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
4
4
  email: string;
@@ -23,8 +23,13 @@ export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import(
23
23
  allowedDomain: string;
24
24
  workspaceUrl: string;
25
25
  requiredAuthProvider: "google";
26
+ workspaceAppDefaultVisibility: WorkspaceAppDefaultVisibility;
26
27
  a2aSecretSet: boolean;
27
28
  }>>;
29
+ /** PUT /_agent-native/org/workspace-app-default-visibility - org admins only */
30
+ export declare const setWorkspaceAppDefaultVisibilityHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
31
+ visibility: WorkspaceAppDefaultVisibility;
32
+ }>>;
28
33
  /** POST /_agent-native/org — create a new organization */
29
34
  export declare const createOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
30
35
  id: string;
@@ -35,6 +35,7 @@ import { getSession } from "../server/auth.js";
35
35
  import { renderInviteEmail } from "../server/email-templates.js";
36
36
  import { sendEmail, isEmailConfigured } from "../server/email.js";
37
37
  import { readBody } from "../server/h3-helpers.js";
38
+ import { getOrgSetting, putOrgSetting } from "../settings/org-settings.js";
38
39
  import { setActiveOrgId } from "./active-org.js";
39
40
  import { setRequiredAuthProvider } from "./auth-policy.js";
40
41
  import { invalidateDomainMatchCache } from "./auto-join-domain.js";
@@ -42,6 +43,14 @@ import { getOrgContext, createOrganization } from "./context.js";
42
43
  import { isFreeEmailProvider } from "./free-email-providers.js";
43
44
  import { invalidateMemberOrgCaches } from "./request-org-cache.js";
44
45
  import { parseWorkspaceUrl } from "./workspace-url.js";
46
+ const WORKSPACE_APP_DEFAULT_VISIBILITY_KEY = "workspace-app-default-visibility";
47
+ function normalizeWorkspaceAppDefaultVisibility(value) {
48
+ if (value === "private" || value === "org")
49
+ return value;
50
+ if (value == null)
51
+ return "org";
52
+ throw new Error("Workspace app default visibility is invalid; refusing to widen access.");
53
+ }
45
54
  function getInviteAppUrl(event) {
46
55
  return getAppProductionUrl(event);
47
56
  }
@@ -119,6 +128,11 @@ export const getMyOrgHandler = defineEventHandler(async (event) => {
119
128
  }
120
129
  }
121
130
  const isOwnerOrAdmin = ctx.role === "owner" || ctx.role === "admin";
131
+ let workspaceAppDefaultVisibility = "org";
132
+ if (ctx.orgId) {
133
+ const setting = await getOrgSetting(ctx.orgId, WORKSPACE_APP_DEFAULT_VISIBILITY_KEY);
134
+ workspaceAppDefaultVisibility = normalizeWorkspaceAppDefaultVisibility(setting?.visibility);
135
+ }
122
136
  const invitesRes = await e.execute({
123
137
  // Case-insensitive match: invitations are stored with whatever case
124
138
  // the inviter typed, but the session email may be normalized
@@ -147,6 +161,7 @@ export const getMyOrgHandler = defineEventHandler(async (event) => {
147
161
  allowedDomain,
148
162
  workspaceUrl,
149
163
  requiredAuthProvider,
164
+ workspaceAppDefaultVisibility,
150
165
  // Never serialize the A2A secret here. This route runs on every page load,
151
166
  // so the value would sit in JSON any script on the page can read, and it
152
167
  // signs the JWTs peers accept as first-party callers. Reveal is an explicit
@@ -154,6 +169,34 @@ export const getMyOrgHandler = defineEventHandler(async (event) => {
154
169
  a2aSecretSet: isOwnerOrAdmin ? a2aSecretSet : undefined,
155
170
  };
156
171
  });
172
+ /** PUT /_agent-native/org/workspace-app-default-visibility - org admins only */
173
+ export const setWorkspaceAppDefaultVisibilityHandler = defineEventHandler(async (event) => {
174
+ const ctx = await getOrgContext(event);
175
+ if (ctx.role !== "owner" && ctx.role !== "admin") {
176
+ throw createError({
177
+ statusCode: 403,
178
+ message: "Only organization admins can change app defaults.",
179
+ });
180
+ }
181
+ if (!ctx.orgId) {
182
+ throw createError({
183
+ statusCode: 400,
184
+ message: "Join an organization before changing app defaults.",
185
+ });
186
+ }
187
+ const body = await readBody(event);
188
+ if (body?.visibility !== "private" && body?.visibility !== "org") {
189
+ throw createError({
190
+ statusCode: 400,
191
+ message: "visibility must be either private or org.",
192
+ });
193
+ }
194
+ const visibility = body.visibility;
195
+ await putOrgSetting(ctx.orgId, WORKSPACE_APP_DEFAULT_VISIBILITY_KEY, {
196
+ visibility,
197
+ });
198
+ return { visibility };
199
+ });
157
200
  /** POST /_agent-native/org — create a new organization */
158
201
  export const createOrgHandler = defineEventHandler(async (event) => {
159
202
  const session = await getSession(event);
@@ -1,4 +1,4 @@
1
- export type { OrgRole, OrgContext, OrgSummary, OrgInvitationSummary, OrgInfo, OrgMember, OrgPendingInvitation, RequiredAuthProvider, } from "./types.js";
1
+ export type { OrgRole, OrgContext, OrgSummary, OrgInvitationSummary, OrgInfo, OrgMember, OrgPendingInvitation, RequiredAuthProvider, WorkspaceAppDefaultVisibility, } from "./types.js";
2
2
  export { canInviteOrgMembers, canManageOrg, canManageOrgDomain, orgRoleAtLeast, orgRoleRank, } from "./permissions.js";
3
3
  export { getOrgContext, getOrgDomain, getOrgA2ASecret, getA2ASecretByDomain, resolveOrgByDomain, resolveOrgIdForEmail, createOrganization, } from "./context.js";
4
4
  export { implicitServiceOrgRole, parseServiceIdentityEmail, } from "./service-identity.js";
@@ -11,8 +11,8 @@ export type { AppRoles, AppRolesDescriptor, AppRoleCaller, AppRoleLookup, AppMem
11
11
  export { ORG_MIGRATIONS } from "./migrations.js";
12
12
  export { getRequiredAuthProviderForEmail, getRequiredAuthProviderForOrg, isGoogleSignInRequiredForEmail, setRequiredAuthProvider, } from "./auth-policy.js";
13
13
  export { createOrgPlugin, defaultOrgPlugin } from "./plugin.js";
14
- export { organizations, orgMembers, orgInvitations, appMemberRoles, } from "./schema.js";
15
- export { getMyOrgHandler, createOrgHandler, updateOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setRequiredAuthProviderHandler, } from "./handlers.js";
14
+ export { organizations, orgMembers, orgInvitations, appMemberRoles, workspaceApps, workspaceAppShares, } from "./schema.js";
15
+ export { getMyOrgHandler, createOrgHandler, updateOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setRequiredAuthProviderHandler, setWorkspaceAppDefaultVisibilityHandler, } from "./handlers.js";
16
16
  export { listAppRolesHandler, setAppRoleHandler, } from "./app-roles-handlers.js";
17
17
  export { isFreeEmailProvider } from "./free-email-providers.js";
18
18
  export { isOrgMember } from "./membership.js";
package/dist/org/index.js CHANGED
@@ -10,10 +10,10 @@ export { getRequiredAuthProviderForEmail, getRequiredAuthProviderForOrg, isGoogl
10
10
  export { createOrgPlugin, defaultOrgPlugin } from "./plugin.js";
11
11
  // Drizzle schema (re-exported so templates can write typed queries against
12
12
  // org tables without redefining the schema themselves).
13
- export { organizations, orgMembers, orgInvitations, appMemberRoles, } from "./schema.js";
13
+ export { organizations, orgMembers, orgInvitations, appMemberRoles, workspaceApps, workspaceAppShares, } from "./schema.js";
14
14
  // Individual handlers — exported so templates can compose a custom org plugin
15
15
  // while still using the framework-provided handlers.
16
- export { getMyOrgHandler, createOrgHandler, updateOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setRequiredAuthProviderHandler, } from "./handlers.js";
16
+ export { getMyOrgHandler, createOrgHandler, updateOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setRequiredAuthProviderHandler, setWorkspaceAppDefaultVisibilityHandler, } from "./handlers.js";
17
17
  export { listAppRolesHandler, setAppRoleHandler, } from "./app-roles-handlers.js";
18
18
  export { isFreeEmailProvider } from "./free-email-providers.js";
19
19
  export { isOrgMember } from "./membership.js";
@@ -132,4 +132,37 @@ export const ORG_MIGRATIONS = [
132
132
  version: 1014,
133
133
  sql: `ALTER TABLE organizations ADD COLUMN IF NOT EXISTS required_auth_provider TEXT`,
134
134
  },
135
+ {
136
+ version: 1015,
137
+ sql: `CREATE TABLE IF NOT EXISTS workspace_apps (
138
+ id TEXT PRIMARY KEY,
139
+ owner_email TEXT NOT NULL,
140
+ org_id TEXT,
141
+ visibility TEXT NOT NULL DEFAULT 'org',
142
+ name TEXT NOT NULL,
143
+ description TEXT,
144
+ path TEXT NOT NULL,
145
+ created_at INTEGER NOT NULL,
146
+ updated_at INTEGER NOT NULL
147
+ )`,
148
+ },
149
+ {
150
+ version: 1016,
151
+ sql: `CREATE TABLE IF NOT EXISTS workspace_app_shares (
152
+ id TEXT PRIMARY KEY,
153
+ resource_id TEXT NOT NULL,
154
+ principal_type TEXT NOT NULL,
155
+ principal_id TEXT NOT NULL,
156
+ role TEXT NOT NULL DEFAULT 'viewer',
157
+ created_at TEXT NOT NULL,
158
+ created_by TEXT NOT NULL DEFAULT '',
159
+ UNIQUE(resource_id, principal_type, principal_id)
160
+ )`,
161
+ },
162
+ {
163
+ version: 1017,
164
+ name: "workspace-app-access-indexes",
165
+ sql: `CREATE INDEX IF NOT EXISTS workspace_apps_org_visibility_idx
166
+ ON workspace_apps (org_id, visibility)`,
167
+ },
135
168
  ];
@@ -2,7 +2,7 @@ import { defineEventHandler, setResponseStatus, getMethod, getRequestURL, } from
2
2
  import { runMigrations } from "../db/migrations.js";
3
3
  import { awaitBootstrap, getH3App, FRAMEWORK_PREFIX, markDefaultPluginProvided, } from "../server/framework-request-handler.js";
4
4
  import { listAppRolesHandler, setAppRoleHandler, } from "./app-roles-handlers.js";
5
- import { getMyOrgHandler, createOrgHandler, updateOrgHandler, deleteOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, joinByDomainHandler, setDomainHandler, setWorkspaceUrlHandler, setRequiredAuthProviderHandler, revealA2ASecretHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, } from "./handlers.js";
5
+ import { getMyOrgHandler, createOrgHandler, updateOrgHandler, deleteOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, joinByDomainHandler, setDomainHandler, setWorkspaceUrlHandler, setRequiredAuthProviderHandler, revealA2ASecretHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setWorkspaceAppDefaultVisibilityHandler, } from "./handlers.js";
6
6
  import { ORG_MIGRATIONS } from "./migrations.js";
7
7
  const ORG_PREFIX = `${FRAMEWORK_PREFIX}/org`;
8
8
  /**
@@ -97,6 +97,15 @@ export function createOrgPlugin() {
97
97
  }
98
98
  return removeMemberHandler(event);
99
99
  }));
100
+ // PUT /workspace-app-default-visibility — org admins choose the default
101
+ // for newly created workspace apps. Existing apps retain their setting.
102
+ app.use(`${ORG_PREFIX}/workspace-app-default-visibility`, defineEventHandler(async (event) => {
103
+ if (getMethod(event) !== "PUT") {
104
+ setResponseStatus(event, 405);
105
+ return { error: "Method not allowed" };
106
+ }
107
+ return setWorkspaceAppDefaultVisibilityHandler(event);
108
+ }));
100
109
  // /invitations and /invitations/:id/accept — same pattern.
101
110
  app.use(`${ORG_PREFIX}/invitations`, defineEventHandler(async (event) => {
102
111
  const tail = getRequestURL(event).pathname || "/";