@agent-team-foundation/first-tree-hub 0.14.4 → 0.14.6

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 (101) hide show
  1. package/dist/bootstrap-BmeaRhRp.mjs +3 -0
  2. package/dist/{bootstrap-CQQGgIx1.mjs → bootstrap-CmkHQsnS.mjs} +24 -16
  3. package/dist/cli/index.mjs +6 -94
  4. package/dist/{dist-CrdnqZjv.mjs → feishu-BE7QRxnE.mjs} +170 -379
  5. package/dist/feishu-De9_bA91.mjs +3 -0
  6. package/dist/index.mjs +5 -12
  7. package/dist/saas-connect-CNY9Ve5V.mjs +13748 -0
  8. package/package.json +4 -12
  9. package/dist/chunk-BSw8zbkd.mjs +0 -37
  10. package/dist/client-BPRIfrOT-CoV_2o7e.mjs +0 -4230
  11. package/dist/client-CEdYVnoj-BGiGcJbH.mjs +0 -7
  12. package/dist/dist-LgF7LHpE.mjs +0 -430
  13. package/dist/drizzle/0000_shocking_darkhawk.sql +0 -92
  14. package/dist/drizzle/0001_v2_schema_updates.sql +0 -26
  15. package/dist/drizzle/0002_adapter_tables.sql +0 -64
  16. package/dist/drizzle/0003_feishu_adapter.sql +0 -21
  17. package/dist/drizzle/0004_adapter_refactor.sql +0 -13
  18. package/dist/drizzle/0005_delegate_mention.sql +0 -1
  19. package/dist/drizzle/0006_agent_tree_path.sql +0 -1
  20. package/dist/drizzle/0007_decouple_context_tree.sql +0 -2
  21. package/dist/drizzle/0008_uuid_identity.sql +0 -12
  22. package/dist/drizzle/0009_agent_runtime_m1.sql +0 -31
  23. package/dist/drizzle/0010_cloud_multi_tenancy.sql +0 -34
  24. package/dist/drizzle/0011_org_uuid_pk.sql +0 -22
  25. package/dist/drizzle/0012_session_level_state.sql +0 -19
  26. package/dist/drizzle/0013_hub_tasks.sql +0 -38
  27. package/dist/drizzle/0014_drop_task_fks.sql +0 -9
  28. package/dist/drizzle/0015_member_system.sql +0 -34
  29. package/dist/drizzle/0016_strange_havok.sql +0 -25
  30. package/dist/drizzle/0017_session_outputs_unique.sql +0 -1
  31. package/dist/drizzle/0018_agent_visibility.sql +0 -13
  32. package/dist/drizzle/0019_agent_configs.sql +0 -30
  33. package/dist/drizzle/0020_unified_user_token.sql +0 -154
  34. package/dist/drizzle/0021_drop_agents_profile.sql +0 -10
  35. package/dist/drizzle/0022_session_events.sql +0 -32
  36. package/dist/drizzle/0023_clients_org_scoping.sql +0 -40
  37. package/dist/drizzle/0024_display_name_not_null.sql +0 -31
  38. package/dist/drizzle/0025_inbox_silent_entries.sql +0 -53
  39. package/dist/drizzle/0026_saas_onboarding.sql +0 -153
  40. package/dist/drizzle/0027_runtime_provider.sql +0 -10
  41. package/dist/drizzle/0028_auth_identity_user_github_unique.sql +0 -12
  42. package/dist/drizzle/0029_direct_agent_only_mention_only.sql +0 -28
  43. package/dist/drizzle/0030_chat_first_workspace.sql +0 -129
  44. package/dist/drizzle/0031_drop_system_configs.sql +0 -11
  45. package/dist/drizzle/0032_organization_settings.sql +0 -36
  46. package/dist/drizzle/0033_onboarding_dismissed_at.sql +0 -13
  47. package/dist/drizzle/0034_pending_questions.sql +0 -34
  48. package/dist/drizzle/0035_drop_hub_tasks.sql +0 -7
  49. package/dist/drizzle/0036_github_entity_chat_mappings.sql +0 -47
  50. package/dist/drizzle/0037_github_app_installations.sql +0 -52
  51. package/dist/drizzle/0038_chat_membership_user_state.sql +0 -223
  52. package/dist/drizzle/0039_drop_chat_participants_subscriptions.sql +0 -26
  53. package/dist/drizzle/0040_chat_user_state_engagement.sql +0 -24
  54. package/dist/drizzle/0041_notifications_dedup_key.sql +0 -29
  55. package/dist/drizzle/0042_notifications_drop_legacy_types.sql +0 -36
  56. package/dist/drizzle/0043_onboarding_completed_at.sql +0 -32
  57. package/dist/drizzle/0044_agent_avatar_color.sql +0 -11
  58. package/dist/drizzle/0045_agent_avatar_image.sql +0 -17
  59. package/dist/drizzle/meta/0000_snapshot.json +0 -687
  60. package/dist/drizzle/meta/0001_snapshot.json +0 -687
  61. package/dist/drizzle/meta/0012_snapshot.json +0 -1451
  62. package/dist/drizzle/meta/0013_snapshot.json +0 -1771
  63. package/dist/drizzle/meta/0014_snapshot.json +0 -1717
  64. package/dist/drizzle/meta/0016_snapshot.json +0 -1917
  65. package/dist/drizzle/meta/0018_snapshot.json +0 -1938
  66. package/dist/drizzle/meta/_journal.json +0 -328
  67. package/dist/esm-iadMkGbV.mjs +0 -1516
  68. package/dist/execAsync-DUfRkc4a.mjs +0 -10
  69. package/dist/execAsync-YbEZSOYd.mjs +0 -10
  70. package/dist/feishu-DNoBroKK.mjs +0 -53
  71. package/dist/from-DQ7eNRwu.mjs +0 -3840
  72. package/dist/getMachineId-bsd-BmasEOJr.mjs +0 -27
  73. package/dist/getMachineId-bsd-Dh3h0DDE.mjs +0 -27
  74. package/dist/getMachineId-darwin-CuhM3hfZ.mjs +0 -24
  75. package/dist/getMachineId-darwin-D9wR0SLj.mjs +0 -24
  76. package/dist/getMachineId-linux-CYfb0oxZ.mjs +0 -20
  77. package/dist/getMachineId-linux-D8ZaSjAC.mjs +0 -20
  78. package/dist/getMachineId-unsupported-Cu3iisaD.mjs +0 -15
  79. package/dist/getMachineId-unsupported-DZqI4ZT5.mjs +0 -15
  80. package/dist/getMachineId-win-8ZJbtrdf.mjs +0 -26
  81. package/dist/getMachineId-win-DT-hqwVp.mjs +0 -26
  82. package/dist/invitation-C9m2gQx4-C_4f5VTs.mjs +0 -4
  83. package/dist/invitation-D_ENPHyj-5ETiae5r.mjs +0 -167
  84. package/dist/logger-core-BTmvdflj-DjW8FM4T.mjs +0 -146
  85. package/dist/multipart-parser-QRu3OKK4.mjs +0 -294
  86. package/dist/observability-BAScT_5S-BcW9HgkG.mjs +0 -96129
  87. package/dist/observability-eLA9iNK_.mjs +0 -5
  88. package/dist/saas-connect-Da55XxRX.mjs +0 -21635
  89. package/dist/src-DFlbpJfU.mjs +0 -1176
  90. package/dist/src-DNBS5Yjj.mjs +0 -735
  91. package/dist/uuid-DbS_4vFh-iFghv4zA.mjs +0 -129
  92. package/dist/web/assets/index-9wK0udbH.js +0 -416
  93. package/dist/web/assets/index-C7x7O7dG.js +0 -11
  94. package/dist/web/assets/index-DE7Q3QWE.css +0 -1
  95. package/dist/web/favicon.svg +0 -9
  96. package/dist/web/fonts/inter-latin-ext.woff2 +0 -0
  97. package/dist/web/fonts/inter-latin.woff2 +0 -0
  98. package/dist/web/fonts/jetbrains-mono-latin-ext.woff2 +0 -0
  99. package/dist/web/fonts/jetbrains-mono-latin.woff2 +0 -0
  100. package/dist/web/index.html +0 -39
  101. /package/dist/{cli-fetch--tiwKm5S.mjs → cli-fetch-BGVItZxo.mjs} +0 -0
@@ -1,27 +0,0 @@
1
- import { a as __toCommonJS, i as __require, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- import { t as require_execAsync } from "./execAsync-DUfRkc4a.mjs";
4
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.0_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-bsd.js
5
- var require_getMachineId_bsd = /* @__PURE__ */ __commonJSMin(((exports) => {
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.getMachineId = void 0;
8
- const fs_1 = __require("fs");
9
- const execAsync_1 = require_execAsync();
10
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
11
- async function getMachineId() {
12
- try {
13
- return (await fs_1.promises.readFile("/etc/hostid", { encoding: "utf8" })).trim();
14
- } catch (e) {
15
- api_1.diag.debug(`error reading machine id: ${e}`);
16
- }
17
- try {
18
- return (await (0, execAsync_1.execAsync)("kenv -q smbios.system.uuid")).stdout.trim();
19
- } catch (e) {
20
- api_1.diag.debug(`error reading machine id: ${e}`);
21
- }
22
- }
23
- exports.getMachineId = getMachineId;
24
- }));
25
- //#endregion
26
- export default require_getMachineId_bsd();
27
- export {};
@@ -1,27 +0,0 @@
1
- import { a as __toCommonJS, i as __require, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- import { t as require_execAsync } from "./execAsync-YbEZSOYd.mjs";
4
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.1_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-bsd.js
5
- var require_getMachineId_bsd = /* @__PURE__ */ __commonJSMin(((exports) => {
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.getMachineId = void 0;
8
- const fs_1 = __require("fs");
9
- const execAsync_1 = require_execAsync();
10
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
11
- async function getMachineId() {
12
- try {
13
- return (await fs_1.promises.readFile("/etc/hostid", { encoding: "utf8" })).trim();
14
- } catch (e) {
15
- api_1.diag.debug(`error reading machine id: ${e}`);
16
- }
17
- try {
18
- return (await (0, execAsync_1.execAsync)("kenv -q smbios.system.uuid")).stdout.trim();
19
- } catch (e) {
20
- api_1.diag.debug(`error reading machine id: ${e}`);
21
- }
22
- }
23
- exports.getMachineId = getMachineId;
24
- }));
25
- //#endregion
26
- export default require_getMachineId_bsd();
27
- export {};
@@ -1,24 +0,0 @@
1
- import { a as __toCommonJS, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- import { t as require_execAsync } from "./execAsync-DUfRkc4a.mjs";
4
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.0_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-darwin.js
5
- var require_getMachineId_darwin = /* @__PURE__ */ __commonJSMin(((exports) => {
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.getMachineId = void 0;
8
- const execAsync_1 = require_execAsync();
9
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
10
- async function getMachineId() {
11
- try {
12
- const idLine = (await (0, execAsync_1.execAsync)("ioreg -rd1 -c \"IOPlatformExpertDevice\"")).stdout.split("\n").find((line) => line.includes("IOPlatformUUID"));
13
- if (!idLine) return;
14
- const parts = idLine.split("\" = \"");
15
- if (parts.length === 2) return parts[1].slice(0, -1);
16
- } catch (e) {
17
- api_1.diag.debug(`error reading machine id: ${e}`);
18
- }
19
- }
20
- exports.getMachineId = getMachineId;
21
- }));
22
- //#endregion
23
- export default require_getMachineId_darwin();
24
- export {};
@@ -1,24 +0,0 @@
1
- import { a as __toCommonJS, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- import { t as require_execAsync } from "./execAsync-YbEZSOYd.mjs";
4
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.1_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-darwin.js
5
- var require_getMachineId_darwin = /* @__PURE__ */ __commonJSMin(((exports) => {
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.getMachineId = void 0;
8
- const execAsync_1 = require_execAsync();
9
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
10
- async function getMachineId() {
11
- try {
12
- const idLine = (await (0, execAsync_1.execAsync)("ioreg -rd1 -c \"IOPlatformExpertDevice\"")).stdout.split("\n").find((line) => line.includes("IOPlatformUUID"));
13
- if (!idLine) return;
14
- const parts = idLine.split("\" = \"");
15
- if (parts.length === 2) return parts[1].slice(0, -1);
16
- } catch (e) {
17
- api_1.diag.debug(`error reading machine id: ${e}`);
18
- }
19
- }
20
- exports.getMachineId = getMachineId;
21
- }));
22
- //#endregion
23
- export default require_getMachineId_darwin();
24
- export {};
@@ -1,20 +0,0 @@
1
- import { a as __toCommonJS, i as __require, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.0_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-linux.js
4
- var require_getMachineId_linux = /* @__PURE__ */ __commonJSMin(((exports) => {
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getMachineId = void 0;
7
- const fs_1 = __require("fs");
8
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
9
- async function getMachineId() {
10
- for (const path of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) try {
11
- return (await fs_1.promises.readFile(path, { encoding: "utf8" })).trim();
12
- } catch (e) {
13
- api_1.diag.debug(`error reading machine id: ${e}`);
14
- }
15
- }
16
- exports.getMachineId = getMachineId;
17
- }));
18
- //#endregion
19
- export default require_getMachineId_linux();
20
- export {};
@@ -1,20 +0,0 @@
1
- import { a as __toCommonJS, i as __require, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.1_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-linux.js
4
- var require_getMachineId_linux = /* @__PURE__ */ __commonJSMin(((exports) => {
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getMachineId = void 0;
7
- const fs_1 = __require("fs");
8
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
9
- async function getMachineId() {
10
- for (const path of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) try {
11
- return (await fs_1.promises.readFile(path, { encoding: "utf8" })).trim();
12
- } catch (e) {
13
- api_1.diag.debug(`error reading machine id: ${e}`);
14
- }
15
- }
16
- exports.getMachineId = getMachineId;
17
- }));
18
- //#endregion
19
- export default require_getMachineId_linux();
20
- export {};
@@ -1,15 +0,0 @@
1
- import { a as __toCommonJS, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.1_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-unsupported.js
4
- var require_getMachineId_unsupported = /* @__PURE__ */ __commonJSMin(((exports) => {
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getMachineId = void 0;
7
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
8
- async function getMachineId() {
9
- api_1.diag.debug("could not read machine-id: unsupported platform");
10
- }
11
- exports.getMachineId = getMachineId;
12
- }));
13
- //#endregion
14
- export default require_getMachineId_unsupported();
15
- export {};
@@ -1,15 +0,0 @@
1
- import { a as __toCommonJS, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.0_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-unsupported.js
4
- var require_getMachineId_unsupported = /* @__PURE__ */ __commonJSMin(((exports) => {
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getMachineId = void 0;
7
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
8
- async function getMachineId() {
9
- api_1.diag.debug("could not read machine-id: unsupported platform");
10
- }
11
- exports.getMachineId = getMachineId;
12
- }));
13
- //#endregion
14
- export default require_getMachineId_unsupported();
15
- export {};
@@ -1,26 +0,0 @@
1
- import { a as __toCommonJS, i as __require, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- import { t as require_execAsync } from "./execAsync-DUfRkc4a.mjs";
4
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.0_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-win.js
5
- var require_getMachineId_win = /* @__PURE__ */ __commonJSMin(((exports) => {
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.getMachineId = void 0;
8
- const process = __require("process");
9
- const execAsync_1 = require_execAsync();
10
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
11
- async function getMachineId() {
12
- const args = "QUERY HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography /v MachineGuid";
13
- let command = "%windir%\\System32\\REG.exe";
14
- if (process.arch === "ia32" && "PROCESSOR_ARCHITEW6432" in process.env) command = "%windir%\\sysnative\\cmd.exe /c " + command;
15
- try {
16
- const parts = (await (0, execAsync_1.execAsync)(`${command} ${args}`)).stdout.split("REG_SZ");
17
- if (parts.length === 2) return parts[1].trim();
18
- } catch (e) {
19
- api_1.diag.debug(`error reading machine id: ${e}`);
20
- }
21
- }
22
- exports.getMachineId = getMachineId;
23
- }));
24
- //#endregion
25
- export default require_getMachineId_win();
26
- export {};
@@ -1,26 +0,0 @@
1
- import { a as __toCommonJS, i as __require, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
2
- import { n as init_esm, t as esm_exports } from "./esm-iadMkGbV.mjs";
3
- import { t as require_execAsync } from "./execAsync-YbEZSOYd.mjs";
4
- //#region ../../node_modules/.pnpm/@opentelemetry+resources@2.7.1_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/resources/build/src/detectors/platform/node/machine-id/getMachineId-win.js
5
- var require_getMachineId_win = /* @__PURE__ */ __commonJSMin(((exports) => {
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.getMachineId = void 0;
8
- const process = __require("process");
9
- const execAsync_1 = require_execAsync();
10
- const api_1 = (init_esm(), __toCommonJS(esm_exports));
11
- async function getMachineId() {
12
- const args = "QUERY HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography /v MachineGuid";
13
- let command = "%windir%\\System32\\REG.exe";
14
- if (process.arch === "ia32" && "PROCESSOR_ARCHITEW6432" in process.env) command = "%windir%\\sysnative\\cmd.exe /c " + command;
15
- try {
16
- const parts = (await (0, execAsync_1.execAsync)(`${command} ${args}`)).stdout.split("REG_SZ");
17
- if (parts.length === 2) return parts[1].trim();
18
- } catch (e) {
19
- api_1.diag.debug(`error reading machine id: ${e}`);
20
- }
21
- }
22
- exports.getMachineId = getMachineId;
23
- }));
24
- //#endregion
25
- export default require_getMachineId_win();
26
- export {};
@@ -1,4 +0,0 @@
1
- import "./dist-CrdnqZjv.mjs";
2
- import "./uuid-DbS_4vFh-iFghv4zA.mjs";
3
- import { s as previewInvitation } from "./invitation-D_ENPHyj-5ETiae5r.mjs";
4
- export { previewInvitation };
@@ -1,167 +0,0 @@
1
- import { c as NotFoundError, d as users, f as uuidv7, u as organizations } from "./uuid-DbS_4vFh-iFghv4zA.mjs";
2
- import { randomBytes } from "node:crypto";
3
- import { and, desc, eq, gt, isNull, or } from "drizzle-orm";
4
- import { index, pgTable, text, timestamp } from "drizzle-orm/pg-core";
5
- //#region ../server/dist/invitation-D_ENPHyj.mjs
6
- /**
7
- * Org-level invitation links. v1 enforces "one active link per org" via a
8
- * partial UNIQUE index added in the SQL migration (Drizzle's TS DSL does not
9
- * yet model partial uniques). Rotating a link sets `revoked_at` on the prior
10
- * row and inserts a new one in the same transaction; revoked rows stay for
11
- * audit but no longer satisfy the partial uniqueness predicate.
12
- *
13
- * `role` is fixed to `'member'` by the v1 API but stored on the row so a
14
- * future "invite as admin" feature is a route change, not a schema change.
15
- *
16
- * `expires_at` is left unset by the v1 rotate flow — invite links don't
17
- * auto-expire. The column exists so an admin can opt into expiry later (and
18
- * the partial unique predicate already filters on it).
19
- */
20
- const invitations = pgTable("invitations", {
21
- id: text("id").primaryKey(),
22
- organizationId: text("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
23
- token: text("token").notNull().unique(),
24
- role: text("role").notNull().default("member"),
25
- expiresAt: timestamp("expires_at", { withTimezone: true }),
26
- revokedAt: timestamp("revoked_at", { withTimezone: true }),
27
- createdBy: text("created_by").notNull().references(() => users.id),
28
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
29
- }, (table) => [index("idx_invitations_token").on(table.token), index("idx_invitations_org").on(table.organizationId)]);
30
- /** Audit row for every successful redemption — v1 admins inspect via DB. */
31
- const invitationRedemptions = pgTable("invitation_redemptions", {
32
- id: text("id").primaryKey(),
33
- invitationId: text("invitation_id").notNull().references(() => invitations.id, { onDelete: "cascade" }),
34
- userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
35
- redeemedAt: timestamp("redeemed_at", { withTimezone: true }).notNull().defaultNow(),
36
- ip: text("ip"),
37
- userAgent: text("user_agent")
38
- }, (table) => [index("idx_invitation_redemptions_invitation").on(table.invitationId), index("idx_invitation_redemptions_user").on(table.userId)]);
39
- const TOKEN_BYTES = 32;
40
- /**
41
- * Default invite-link TTL — authoritative server-side value. Tightening
42
- * "anyone with this link can join" to a bounded window is the primary
43
- * mitigation for accidental link leakage (admin pasting into a public
44
- * Slack channel, forwarded email chains, screen-share captures, etc).
45
- * 7 days mirrors what GitHub and Vercel default to; longer windows put
46
- * more leak surface on the same token. Admins extend by clicking Rotate
47
- * (which mints a fresh 7-day link in one transaction).
48
- *
49
- * The mirror constant in `@…shared/schemas/invitation.ts` exists so the
50
- * web UI can render "expires in 7 days" copy without an extra round-trip.
51
- */
52
- const INVITATION_DEFAULT_TTL_MS = 10080 * 60 * 1e3;
53
- function generateInvitationToken() {
54
- return randomBytes(TOKEN_BYTES).toString("base64url");
55
- }
56
- function defaultExpiry() {
57
- return new Date(Date.now() + INVITATION_DEFAULT_TTL_MS);
58
- }
59
- /**
60
- * Return the *active* invitation for `orgId`, or null if none exists.
61
- * "Active" = not revoked AND not expired.
62
- *
63
- * Mirrors the predicate of the partial UNIQUE index `uq_invitations_active_per_org`,
64
- * so a successful `getActiveInvitation` is the same row the index protects.
65
- */
66
- async function getActiveInvitation(db, orgId) {
67
- const now = /* @__PURE__ */ new Date();
68
- const [row] = await db.select().from(invitations).where(and(eq(invitations.organizationId, orgId), isNull(invitations.revokedAt), or(isNull(invitations.expiresAt), gt(invitations.expiresAt, now)))).orderBy(desc(invitations.createdAt)).limit(1);
69
- return row ?? null;
70
- }
71
- /**
72
- * Get-or-create the active invitation for `orgId`. Idempotent so the admin
73
- * UI can call this on first render without inadvertently creating a fresh
74
- * link every time someone visits Settings.
75
- *
76
- * "Active" is filtered by `getActiveInvitation` (revoked_at IS NULL AND
77
- * not expired). When no active row exists we delegate to `rotateInvitation`
78
- * — that path correctly handles the case where a prior row exists but
79
- * has expired (`revoked_at IS NULL` but `expires_at < now()`). A naked
80
- * INSERT here would trip `uq_invitations_active_per_org` (the partial
81
- * unique index can't filter on `now()`, so it considers expired-but-not-
82
- * revoked rows as still occupying the slot).
83
- */
84
- async function ensureActiveInvitation(db, orgId, createdBy) {
85
- const existing = await getActiveInvitation(db, orgId);
86
- if (existing) return existing;
87
- return rotateInvitation(db, orgId, createdBy);
88
- }
89
- /**
90
- * Rotate the invitation: revoke every non-revoked row for this org (the
91
- * current active link AND any expired-but-not-revoked stragglers) and
92
- * insert a fresh one in a single transaction. Old tokens stop redeeming
93
- * immediately. The new row carries a default 7-day expiry; admin extends
94
- * by rotating again.
95
- */
96
- async function rotateInvitation(db, orgId, createdBy) {
97
- return db.transaction(async (tx) => {
98
- const now = /* @__PURE__ */ new Date();
99
- await tx.update(invitations).set({ revokedAt: now }).where(and(eq(invitations.organizationId, orgId), isNull(invitations.revokedAt)));
100
- const id = uuidv7();
101
- const token = generateInvitationToken();
102
- const [row] = await tx.insert(invitations).values({
103
- id,
104
- organizationId: orgId,
105
- token,
106
- role: "member",
107
- createdBy,
108
- expiresAt: defaultExpiry()
109
- }).returning();
110
- if (!row) throw new Error("Unexpected: INSERT RETURNING produced no row");
111
- return row;
112
- });
113
- }
114
- /**
115
- * Look up an invitation by its public token. Returns null when the token
116
- * is unknown OR when the row exists but is no longer active. Conflating
117
- * "unknown" with "revoked" prevents an attacker from inferring which
118
- * tokens were once valid.
119
- */
120
- async function findActiveByToken(db, token) {
121
- const now = /* @__PURE__ */ new Date();
122
- const [row] = await db.select().from(invitations).where(and(eq(invitations.token, token), isNull(invitations.revokedAt), or(isNull(invitations.expiresAt), gt(invitations.expiresAt, now)))).limit(1);
123
- return row ?? null;
124
- }
125
- /**
126
- * Public preview surfaced on `/invite/:token` before the recipient signs in.
127
- */
128
- async function previewInvitation(db, token) {
129
- const inv = await findActiveByToken(db, token);
130
- if (!inv) throw new NotFoundError("Invitation not found or no longer valid");
131
- const [org] = await db.select({
132
- id: organizations.id,
133
- name: organizations.name,
134
- displayName: organizations.displayName
135
- }).from(organizations).where(eq(organizations.id, inv.organizationId)).limit(1);
136
- if (!org) throw new NotFoundError("Invitation organization not found");
137
- return {
138
- organizationId: org.id,
139
- organizationName: org.name,
140
- organizationDisplayName: org.displayName,
141
- role: inv.role,
142
- expiresAt: inv.expiresAt ? inv.expiresAt.toISOString() : null
143
- };
144
- }
145
- /**
146
- * Record a redemption row. Caller is responsible for executing the join
147
- * (members.insert / status='active' flip) — this is the audit trail only.
148
- */
149
- async function recordRedemption(db, data) {
150
- await db.insert(invitationRedemptions).values({
151
- id: uuidv7(),
152
- invitationId: data.invitationId,
153
- userId: data.userId,
154
- ip: data.ip ?? null,
155
- userAgent: data.userAgent ?? null
156
- });
157
- }
158
- /**
159
- * Build the invite URL surfaced to admins. `publicUrl` should be the
160
- * server's `server.publicUrl` config; pass the request host as fallback in
161
- * dev where publicUrl may be unset.
162
- */
163
- function buildInviteUrl(publicUrl, token) {
164
- return `${publicUrl.replace(/\/+$/, "")}/invite/${token}`;
165
- }
166
- //#endregion
167
- export { invitationRedemptions as a, recordRedemption as c, getActiveInvitation as i, rotateInvitation as l, ensureActiveInvitation as n, invitations as o, findActiveByToken as r, previewInvitation as s, buildInviteUrl as t };
@@ -1,146 +0,0 @@
1
- import { z } from "zod";
2
- import { Writable } from "node:stream";
3
- //#region ../shared/dist/logger-core-BTmvdflj.mjs
4
- /**
5
- * Logger core — format / level primitives shared between server and client.
6
- *
7
- * This module intentionally has no dependency on `pino` so it can live in
8
- * `@agent-team-foundation/first-tree-hub-shared`. Consumers construct their
9
- * own pino instance and pass the output stream built here.
10
- */
11
- const LOG_LEVELS = [
12
- "trace",
13
- "debug",
14
- "info",
15
- "warn",
16
- "error",
17
- "fatal"
18
- ];
19
- const LOG_FORMATS = ["pretty", "json"];
20
- const logLevelSchema = z.enum(LOG_LEVELS);
21
- const logFormatSchema = z.enum(LOG_FORMATS);
22
- /**
23
- * Parse an env-var / config string into a LogLevel. Unknown values fall back
24
- * to `info` so the process never fails to boot on a typo — the caller is
25
- * responsible for emitting a warning when `fellBack` is true.
26
- */
27
- function parseLogLevel(raw) {
28
- if (!raw) return {
29
- level: "info",
30
- fellBack: false
31
- };
32
- const parsed = logLevelSchema.safeParse(raw);
33
- if (parsed.success) return {
34
- level: parsed.data,
35
- fellBack: false
36
- };
37
- return {
38
- level: "info",
39
- fellBack: true
40
- };
41
- }
42
- const LEVEL_LABELS = {
43
- 10: "TRACE",
44
- 20: "DEBUG",
45
- 30: "INFO",
46
- 40: "WARN",
47
- 50: "ERROR",
48
- 60: "FATAL"
49
- };
50
- const LEVEL_COLORS = {
51
- 10: "\x1B[90m",
52
- 20: "\x1B[36m",
53
- 30: "\x1B[32m",
54
- 40: "\x1B[33m",
55
- 50: "\x1B[31m",
56
- 60: "\x1B[35m"
57
- };
58
- const RESET = "\x1B[0m";
59
- const DIM = "\x1B[2m";
60
- const SKIP_KEYS = new Set([
61
- "level",
62
- "time",
63
- "msg",
64
- "module",
65
- "pid",
66
- "hostname",
67
- "v"
68
- ]);
69
- /**
70
- * Pino `redact.paths` entries applied to every root logger in Hub. Keeps the
71
- * list short on purpose — pino's redact walks each path on every log call, so
72
- * we target obvious sensitive field names plus a narrow set of nested forms
73
- * (`*.foo` matches a single nesting level in pino v9).
74
- *
75
- * Values matching these paths are replaced with the censor string `[REDACTED]`.
76
- */
77
- const LOG_REDACT_PATHS = [
78
- "password",
79
- "*.password",
80
- "token",
81
- "*.token",
82
- "accessToken",
83
- "*.accessToken",
84
- "refreshToken",
85
- "*.refreshToken",
86
- "jwt",
87
- "*.jwt",
88
- "secret",
89
- "*.secret",
90
- "apiKey",
91
- "*.apiKey",
92
- "api_key",
93
- "*.api_key",
94
- "credentials",
95
- "*.credentials",
96
- "authorization",
97
- "*.authorization",
98
- "*.headers.cookie",
99
- "*.headers.authorization"
100
- ];
101
- const LOG_REDACT_CENSOR = "[REDACTED]";
102
- function formatPrettyEntry(json) {
103
- const obj = JSON.parse(json);
104
- const level = obj.level;
105
- const label = LEVEL_LABELS[level] ?? "???";
106
- const color = LEVEL_COLORS[level] ?? "";
107
- const time = obj.time ?? (/* @__PURE__ */ new Date()).toISOString();
108
- const module = obj.module ? `[${String(obj.module)}] ` : "";
109
- const msg = obj.msg ?? "";
110
- const extras = [];
111
- let errStack = "";
112
- for (const [k, v] of Object.entries(obj)) {
113
- if (SKIP_KEYS.has(k)) continue;
114
- if (k === "err" && v && typeof v === "object") {
115
- const e = v;
116
- if (e.message) extras.push(`err.message=${String(e.message)}`);
117
- if (typeof e.stack === "string") errStack = `\n${DIM}${e.stack}${RESET}`;
118
- } else extras.push(`${k}=${typeof v === "string" ? v : JSON.stringify(v)}`);
119
- }
120
- const extraStr = extras.length > 0 ? ` ${DIM}${extras.join(" ")}${RESET}` : "";
121
- return `${DIM}${time}${RESET} ${color}${label.padEnd(5)}${RESET} ${module}${msg}${extraStr}${errStack}\n`;
122
- }
123
- function formatLocalTime() {
124
- const d = /* @__PURE__ */ new Date();
125
- return `${d.toLocaleDateString("sv-SE")} ${d.toLocaleTimeString("en-GB", { hour12: false })}`;
126
- }
127
- function createLoggerOutputStream(options) {
128
- const getDest = options.getDestination ?? (() => process.stderr);
129
- return new Writable({ write(chunk, _, callback) {
130
- const text = chunk.toString();
131
- const dest = getDest();
132
- try {
133
- if (options.getFormat() === "pretty") dest.write(formatPrettyEntry(text));
134
- else dest.write(text);
135
- if (options.onJsonEntry) try {
136
- const obj = JSON.parse(text);
137
- options.onJsonEntry(obj);
138
- } catch {}
139
- } catch {
140
- dest.write(text);
141
- }
142
- callback();
143
- } });
144
- }
145
- //#endregion
146
- export { formatLocalTime as a, parseLogLevel as c, createLoggerOutputStream as i, LOG_REDACT_PATHS as n, logFormatSchema as o, SKIP_KEYS as r, logLevelSchema as s, LOG_REDACT_CENSOR as t };