create-hq 10.1.0 → 10.7.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 (70) hide show
  1. package/dist/admin-onboarding.d.ts +42 -0
  2. package/dist/admin-onboarding.d.ts.map +1 -0
  3. package/dist/admin-onboarding.js +460 -0
  4. package/dist/admin-onboarding.js.map +1 -0
  5. package/dist/art.d.ts +17 -0
  6. package/dist/art.d.ts.map +1 -0
  7. package/dist/art.js +171 -0
  8. package/dist/art.js.map +1 -0
  9. package/dist/auth.d.ts +60 -23
  10. package/dist/auth.d.ts.map +1 -1
  11. package/dist/auth.js +219 -116
  12. package/dist/auth.js.map +1 -1
  13. package/dist/cloud.d.ts +26 -0
  14. package/dist/cloud.d.ts.map +1 -0
  15. package/dist/cloud.js +126 -0
  16. package/dist/cloud.js.map +1 -0
  17. package/dist/company-template.d.ts +34 -0
  18. package/dist/company-template.d.ts.map +1 -0
  19. package/dist/company-template.js +142 -0
  20. package/dist/company-template.js.map +1 -0
  21. package/dist/deps.d.ts +2 -0
  22. package/dist/deps.d.ts.map +1 -1
  23. package/dist/deps.js +42 -30
  24. package/dist/deps.js.map +1 -1
  25. package/dist/fetch-template.d.ts +2 -2
  26. package/dist/fetch-template.d.ts.map +1 -1
  27. package/dist/fetch-template.js +54 -38
  28. package/dist/fetch-template.js.map +1 -1
  29. package/dist/git.d.ts.map +1 -1
  30. package/dist/git.js +28 -4
  31. package/dist/git.js.map +1 -1
  32. package/dist/index.js +18 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/invite-command.d.ts +10 -0
  35. package/dist/invite-command.d.ts.map +1 -0
  36. package/dist/invite-command.js +110 -0
  37. package/dist/invite-command.js.map +1 -0
  38. package/dist/invite.d.ts +91 -0
  39. package/dist/invite.d.ts.map +1 -0
  40. package/dist/invite.js +230 -0
  41. package/dist/invite.js.map +1 -0
  42. package/dist/join-flow.d.ts +32 -0
  43. package/dist/join-flow.d.ts.map +1 -0
  44. package/dist/join-flow.js +194 -0
  45. package/dist/join-flow.js.map +1 -0
  46. package/dist/platform.d.ts +2 -2
  47. package/dist/platform.d.ts.map +1 -1
  48. package/dist/platform.js +14 -1
  49. package/dist/platform.js.map +1 -1
  50. package/dist/scaffold.d.ts +4 -1
  51. package/dist/scaffold.d.ts.map +1 -1
  52. package/dist/scaffold.js +152 -41
  53. package/dist/scaffold.js.map +1 -1
  54. package/dist/team-setup.d.ts +58 -0
  55. package/dist/team-setup.d.ts.map +1 -0
  56. package/dist/team-setup.js +237 -0
  57. package/dist/team-setup.js.map +1 -0
  58. package/dist/teams-flow.d.ts +36 -0
  59. package/dist/teams-flow.d.ts.map +1 -0
  60. package/dist/teams-flow.js +134 -0
  61. package/dist/teams-flow.js.map +1 -0
  62. package/dist/tui.d.ts +8 -0
  63. package/dist/tui.d.ts.map +1 -0
  64. package/dist/tui.js +86 -0
  65. package/dist/tui.js.map +1 -0
  66. package/dist/ui.d.ts +17 -0
  67. package/dist/ui.d.ts.map +1 -1
  68. package/dist/ui.js +45 -0
  69. package/dist/ui.js.map +1 -1
  70. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import { Command } from "commander";
3
3
  import { createRequire } from "node:module";
4
4
  import { scaffold } from "./scaffold.js";
5
+ import { runInviteCommand } from "./invite-command.js";
5
6
  const require = createRequire(import.meta.url);
6
7
  const pkg = require("../package.json");
7
8
  const program = new Command();
@@ -9,12 +10,15 @@ program
9
10
  .name("create-hq")
10
11
  .description("Create a new HQ by Indigo — Personal OS for AI Workers")
11
12
  .version(pkg.version)
12
- .argument("[directory]", "where to create HQ", "hq")
13
+ .argument("[directory]", "where to create HQ (prompts if omitted)")
13
14
  .option("--skip-deps", "skip dependency checks")
14
15
  .option("--skip-cli", "don't install @indigoai-us/hq-cli globally")
15
16
  .option("--skip-sync", "don't prompt for cloud sync setup")
17
+ .option("--skip-packages", "don't prompt for package discovery and installation")
16
18
  .option("--tag <version>", "fetch a specific HQ version tag (e.g. v9.1.0)")
17
19
  .option("--local-template <path>", "use a local template directory instead of fetching from GitHub")
20
+ .option("--join <token>", "join a team with an invite token (interactive prompt)")
21
+ .option("--invite <token>", "join a team via invite — direct, no extra prompts")
18
22
  .action(async (directory, options) => {
19
23
  try {
20
24
  await scaffold(directory, options);
@@ -24,5 +28,18 @@ program
24
28
  process.exit(1);
25
29
  }
26
30
  });
31
+ // Standalone invite subcommand for admins to generate invites
32
+ program
33
+ .command("invite")
34
+ .description("Generate an invite code for a new team member")
35
+ .action(async () => {
36
+ try {
37
+ await runInviteCommand();
38
+ }
39
+ catch (err) {
40
+ console.error(err instanceof Error ? err.message : "An unexpected error occurred");
41
+ process.exit(1);
42
+ }
43
+ });
27
44
  program.parse();
28
45
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AAE9D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;KACpB,QAAQ,CAAC,aAAa,EAAE,oBAAoB,EAAE,IAAI,CAAC;KACnD,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,YAAY,EAAE,4CAA4C,CAAC;KAClE,MAAM,CAAC,aAAa,EAAE,mCAAmC,CAAC;KAC1D,MAAM,CAAC,iBAAiB,EAAE,+CAA+C,CAAC;KAC1E,MAAM,CAAC,yBAAyB,EAAE,gEAAgE,CAAC;KACnG,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,OAAO,EAAE,EAAE;IAC3C,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CACpE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AAE9D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;KACpB,QAAQ,CAAC,aAAa,EAAE,yCAAyC,CAAC;KAClE,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,YAAY,EAAE,4CAA4C,CAAC;KAClE,MAAM,CAAC,aAAa,EAAE,mCAAmC,CAAC;KAC1D,MAAM,CAAC,iBAAiB,EAAE,qDAAqD,CAAC;KAChF,MAAM,CAAC,iBAAiB,EAAE,+CAA+C,CAAC;KAC1E,MAAM,CAAC,yBAAyB,EAAE,gEAAgE,CAAC;KACnG,MAAM,CAAC,gBAAgB,EAAE,uDAAuD,CAAC;KACjF,MAAM,CAAC,kBAAkB,EAAE,mDAAmD,CAAC;KAC/E,MAAM,CAAC,KAAK,EAAE,SAA6B,EAAE,OAAO,EAAE,EAAE;IACvD,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CACpE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,8DAA8D;AAC9D,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,gBAAgB,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CACpE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Standalone invite command for admins.
3
+ *
4
+ * Usage: create-hq invite
5
+ *
6
+ * Finds team metadata from the current HQ directory, authenticates
7
+ * the admin, and generates an invite code plus optional org invite.
8
+ */
9
+ export declare function runInviteCommand(): Promise<void>;
10
+ //# sourceMappingURL=invite-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite-command.d.ts","sourceRoot":"","sources":["../src/invite-command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA6EH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA8CtD"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Standalone invite command for admins.
3
+ *
4
+ * Usage: create-hq invite
5
+ *
6
+ * Finds team metadata from the current HQ directory, authenticates
7
+ * the admin, and generates an invite code plus optional org invite.
8
+ */
9
+ import * as fs from "fs";
10
+ import * as path from "path";
11
+ import { execSync } from "child_process";
12
+ import { createInterface } from "readline";
13
+ import chalk from "chalk";
14
+ import { authenticate } from "./teams-flow.js";
15
+ import { inviteLoop } from "./admin-onboarding.js";
16
+ import { warn, info } from "./ui.js";
17
+ function prompt(question, defaultVal) {
18
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
19
+ const suffix = defaultVal ? ` (${defaultVal})` : "";
20
+ return new Promise((resolve) => {
21
+ rl.question(` ? ${question}${suffix} `, (answer) => {
22
+ rl.close();
23
+ resolve(answer.trim() || defaultVal || "");
24
+ });
25
+ });
26
+ }
27
+ /**
28
+ * Find team.json files in companies/ walking up from cwd.
29
+ */
30
+ function findTeams() {
31
+ let dir = process.cwd();
32
+ const root = path.parse(dir).root;
33
+ const teams = [];
34
+ while (dir !== root) {
35
+ const companiesDir = path.join(dir, "companies");
36
+ if (fs.existsSync(companiesDir) && fs.statSync(companiesDir).isDirectory()) {
37
+ for (const entry of fs.readdirSync(companiesDir)) {
38
+ const teamJsonPath = path.join(companiesDir, entry, "team.json");
39
+ if (fs.existsSync(teamJsonPath)) {
40
+ try {
41
+ const meta = JSON.parse(fs.readFileSync(teamJsonPath, "utf-8"));
42
+ let cloneUrl = `https://github.com/${meta.org_login}/hq-${meta.team_slug}.git`;
43
+ try {
44
+ const remote = execSync("git remote get-url origin", {
45
+ cwd: path.join(companiesDir, entry),
46
+ stdio: "pipe",
47
+ })
48
+ .toString()
49
+ .trim();
50
+ if (remote)
51
+ cloneUrl = remote;
52
+ }
53
+ catch {
54
+ // Use constructed URL
55
+ }
56
+ teams.push({
57
+ meta,
58
+ cloneUrl,
59
+ companyDir: path.join(companiesDir, entry),
60
+ });
61
+ }
62
+ catch {
63
+ // Skip malformed team.json
64
+ }
65
+ }
66
+ }
67
+ break;
68
+ }
69
+ dir = path.dirname(dir);
70
+ }
71
+ return teams;
72
+ }
73
+ export async function runInviteCommand() {
74
+ console.log();
75
+ console.log(chalk.bold(" Generate a team invite"));
76
+ console.log();
77
+ const teams = findTeams();
78
+ if (teams.length === 0) {
79
+ warn("No teams found. Run this from your HQ directory (must have companies/*/team.json).");
80
+ info("If you haven't created a team yet, run: npx create-hq");
81
+ return;
82
+ }
83
+ let selected;
84
+ if (teams.length === 1) {
85
+ selected = teams[0];
86
+ info(`Team: ${chalk.cyan(selected.meta.team_name)} (${selected.meta.org_login})`);
87
+ }
88
+ else {
89
+ console.log(" Which team?");
90
+ for (let i = 0; i < teams.length; i++) {
91
+ console.log(chalk.cyan(` [${i + 1}] `) +
92
+ chalk.white(teams[i].meta.team_name) +
93
+ chalk.dim(` (${teams[i].meta.org_login})`));
94
+ }
95
+ const choice = await prompt(`Select (1-${teams.length})`, "1");
96
+ const idx = parseInt(choice, 10) - 1;
97
+ if (idx < 0 || idx >= teams.length) {
98
+ warn("Invalid selection.");
99
+ return;
100
+ }
101
+ selected = teams[idx];
102
+ }
103
+ const auth = await authenticate();
104
+ if (!auth) {
105
+ warn("Authentication required to generate invites.");
106
+ return;
107
+ }
108
+ await inviteLoop(auth, selected.meta, selected.cloneUrl);
109
+ }
110
+ //# sourceMappingURL=invite-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite-command.js","sourceRoot":"","sources":["../src/invite-command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAErC,SAAS,MAAM,CAAC,QAAgB,EAAE,UAAmB;IACnD,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,OAAO,QAAQ,GAAG,MAAM,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE;YAClD,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,UAAU,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAQD;;GAEG;AACH,SAAS,SAAS;IAChB,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;IAClC,MAAM,KAAK,GAAgB,EAAE,CAAC;IAE9B,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACjD,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YAC3E,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC;gBACjD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;gBACjE,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;oBAChC,IAAI,CAAC;wBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CACrB,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CACvB,CAAC;wBAClB,IAAI,QAAQ,GAAG,sBAAsB,IAAI,CAAC,SAAS,OAAO,IAAI,CAAC,SAAS,MAAM,CAAC;wBAC/E,IAAI,CAAC;4BACH,MAAM,MAAM,GAAG,QAAQ,CAAC,2BAA2B,EAAE;gCACnD,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC;gCACnC,KAAK,EAAE,MAAM;6BACd,CAAC;iCACC,QAAQ,EAAE;iCACV,IAAI,EAAE,CAAC;4BACV,IAAI,MAAM;gCAAE,QAAQ,GAAG,MAAM,CAAC;wBAChC,CAAC;wBAAC,MAAM,CAAC;4BACP,sBAAsB;wBACxB,CAAC;wBACD,KAAK,CAAC,IAAI,CAAC;4BACT,IAAI;4BACJ,QAAQ;4BACR,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC;yBAC3C,CAAC,CAAC;oBACL,CAAC;oBAAC,MAAM,CAAC;wBACP,2BAA2B;oBAC7B,CAAC;gBACH,CAAC;YACH,CAAC;YACD,MAAM;QACR,CAAC;QACD,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAE1B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,IAAI,CACF,oFAAoF,CACrF,CAAC;QACF,IAAI,CAAC,uDAAuD,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,IAAI,QAAmB,CAAC;IACxB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CACF,SAAS,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,CAC5E,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;gBACzB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;gBACpC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAC7C,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,KAAK,CAAC,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YAC3B,OAAO;QACT,CAAC;QACD,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAC;IAClC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,CAAC,8CAA8C,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,MAAM,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Invite system for HQ Teams.
3
+ *
4
+ * Tokens are self-contained (no server) — they encode the team coordinates
5
+ * so a new member can join without discovery. Security comes from GitHub:
6
+ * the member still needs org access to clone the private repo.
7
+ *
8
+ * Token format: "hq_" + base64url({ org, repo, slug, teamName, cloneUrl, invitedBy })
9
+ *
10
+ * Admin flow:
11
+ * 1. Generate token from team metadata
12
+ * 2. Optionally send GitHub org invite by email
13
+ * 3. Share token + instructions with member
14
+ *
15
+ * Member flow:
16
+ * 1. Decode token → get team coordinates
17
+ * 2. Auth via GitHub device flow
18
+ * 3. Verify org membership (wait for invite acceptance if needed)
19
+ * 4. Clone repo into companies/{slug}/
20
+ */
21
+ import { type GitHubAuth } from "./auth.js";
22
+ export interface InvitePayload {
23
+ /** GitHub org login (e.g. "indigoai-us") */
24
+ org: string;
25
+ /** Repo name (e.g. "hq-indigo") */
26
+ repo: string;
27
+ /** Team slug (e.g. "indigo") — maps to companies/{slug}/ */
28
+ slug: string;
29
+ /** Human-readable team name */
30
+ teamName: string;
31
+ /** HTTPS clone URL for the repo */
32
+ cloneUrl: string;
33
+ /** GitHub login of the admin who generated the invite */
34
+ invitedBy: string;
35
+ }
36
+ export declare function encodeInviteToken(payload: InvitePayload): string;
37
+ export declare function decodeInviteToken(token: string): InvitePayload | null;
38
+ interface OrgInviteResponse {
39
+ id: number;
40
+ login?: string;
41
+ email?: string;
42
+ role: string;
43
+ }
44
+ /**
45
+ * Send a GitHub org invitation by email.
46
+ *
47
+ * Requires the authenticated user to be an org admin, and the GitHub App
48
+ * to have "Organization > Members: Write" permission.
49
+ *
50
+ * Returns the invitation on success, or an error message string on failure.
51
+ */
52
+ export declare function sendOrgInviteByEmail(auth: GitHubAuth, orgLogin: string, email: string, role?: "direct_member" | "admin"): Promise<{
53
+ ok: true;
54
+ invite: OrgInviteResponse;
55
+ } | {
56
+ ok: false;
57
+ error: string;
58
+ }>;
59
+ /**
60
+ * Check whether a GitHub user is a member of an org.
61
+ */
62
+ export declare function checkOrgMembership(auth: GitHubAuth, orgLogin: string, username: string): Promise<"active" | "pending" | "none">;
63
+ /**
64
+ * Check whether the authenticated user can access a specific repo.
65
+ */
66
+ export declare function checkRepoAccess(auth: GitHubAuth, orgLogin: string, repoName: string): Promise<boolean>;
67
+ /**
68
+ * Generate a ready-to-share invite message for the admin to send to the
69
+ * new member. Designed to be copy-pasted into Slack, email, or text.
70
+ */
71
+ export declare function formatInviteMessage(payload: InvitePayload, token: string, memberEmail?: string): string;
72
+ /**
73
+ * Print the invite details to the console for the admin.
74
+ */
75
+ export declare function printInviteSummary(payload: InvitePayload, token: string, _emailSent?: boolean, memberEmail?: string): void;
76
+ /**
77
+ * Build a mailto: URL pre-populated with the invite message.
78
+ * Opens in the admin's default email client — they just hit Send.
79
+ */
80
+ export declare function buildMailtoUrl(payload: InvitePayload, token: string, recipientEmail: string): string;
81
+ /**
82
+ * Open the admin's email client with a pre-populated invite email.
83
+ */
84
+ export declare function openInviteEmail(payload: InvitePayload, token: string, recipientEmail: string): void;
85
+ /**
86
+ * Copy text to the system clipboard. Cross-platform: pbcopy (macOS),
87
+ * clip (Windows), xclip/xsel (Linux). Returns true on success.
88
+ */
89
+ export declare function copyToClipboard(text: string): boolean;
90
+ export {};
91
+ //# sourceMappingURL=invite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite.d.ts","sourceRoot":"","sources":["../src/invite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAE,KAAK,UAAU,EAA0B,MAAM,WAAW,CAAC;AAIpE,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;CACnB;AAmBD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAEhE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAwBrE;AAID,UAAU,iBAAiB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,eAAe,GAAG,OAAyB,GAChD,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAiCjF;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,CAwBxC;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAOlB;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAoDR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,OAAO,EACpB,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI,CAsBN;AAID;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GACrB,MAAM,CAIR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GACrB,IAAI,CAGN;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAmBrD"}
package/dist/invite.js ADDED
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Invite system for HQ Teams.
3
+ *
4
+ * Tokens are self-contained (no server) — they encode the team coordinates
5
+ * so a new member can join without discovery. Security comes from GitHub:
6
+ * the member still needs org access to clone the private repo.
7
+ *
8
+ * Token format: "hq_" + base64url({ org, repo, slug, teamName, cloneUrl, invitedBy })
9
+ *
10
+ * Admin flow:
11
+ * 1. Generate token from team metadata
12
+ * 2. Optionally send GitHub org invite by email
13
+ * 3. Share token + instructions with member
14
+ *
15
+ * Member flow:
16
+ * 1. Decode token → get team coordinates
17
+ * 2. Auth via GitHub device flow
18
+ * 3. Verify org membership (wait for invite acceptance if needed)
19
+ * 4. Clone repo into companies/{slug}/
20
+ */
21
+ import chalk from "chalk";
22
+ import { execSync } from "child_process";
23
+ import { githubApi, openBrowser } from "./auth.js";
24
+ // ─── Token encode / decode ──────────────────────────────────────────────────
25
+ const TOKEN_PREFIX = "hq_";
26
+ function toBase64Url(str) {
27
+ return Buffer.from(str, "utf-8")
28
+ .toString("base64")
29
+ .replace(/\+/g, "-")
30
+ .replace(/\//g, "_")
31
+ .replace(/=+$/, "");
32
+ }
33
+ function fromBase64Url(b64) {
34
+ const padded = b64.replace(/-/g, "+").replace(/_/g, "/");
35
+ return Buffer.from(padded, "base64").toString("utf-8");
36
+ }
37
+ export function encodeInviteToken(payload) {
38
+ return TOKEN_PREFIX + toBase64Url(JSON.stringify(payload));
39
+ }
40
+ export function decodeInviteToken(token) {
41
+ try {
42
+ const raw = token.startsWith(TOKEN_PREFIX)
43
+ ? token.slice(TOKEN_PREFIX.length)
44
+ : token;
45
+ const json = fromBase64Url(raw);
46
+ const parsed = JSON.parse(json);
47
+ // Validate required fields
48
+ if (typeof parsed.org !== "string" ||
49
+ typeof parsed.repo !== "string" ||
50
+ typeof parsed.slug !== "string" ||
51
+ typeof parsed.teamName !== "string" ||
52
+ typeof parsed.cloneUrl !== "string" ||
53
+ typeof parsed.invitedBy !== "string") {
54
+ return null;
55
+ }
56
+ return parsed;
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
62
+ /**
63
+ * Send a GitHub org invitation by email.
64
+ *
65
+ * Requires the authenticated user to be an org admin, and the GitHub App
66
+ * to have "Organization > Members: Write" permission.
67
+ *
68
+ * Returns the invitation on success, or an error message string on failure.
69
+ */
70
+ export async function sendOrgInviteByEmail(auth, orgLogin, email, role = "direct_member") {
71
+ try {
72
+ const invite = await githubApi(`/orgs/${orgLogin}/invitations`, auth, {
73
+ method: "POST",
74
+ body: JSON.stringify({
75
+ email,
76
+ role,
77
+ }),
78
+ });
79
+ return { ok: true, invite };
80
+ }
81
+ catch (err) {
82
+ const message = err instanceof Error ? err.message : String(err);
83
+ if (message.includes("404") || message.includes("403")) {
84
+ return {
85
+ ok: false,
86
+ error: "The HQ App doesn't have permission to send org invites. " +
87
+ `Please invite the member manually at: https://github.com/orgs/${orgLogin}/people`,
88
+ };
89
+ }
90
+ if (message.includes("422") && /already/i.test(message)) {
91
+ return {
92
+ ok: false,
93
+ error: "This email has already been invited or is already a member.",
94
+ };
95
+ }
96
+ return { ok: false, error: message };
97
+ }
98
+ }
99
+ /**
100
+ * Check whether a GitHub user is a member of an org.
101
+ */
102
+ export async function checkOrgMembership(auth, orgLogin, username) {
103
+ // Check active membership first
104
+ try {
105
+ await githubApi(`/orgs/${orgLogin}/members/${username}`, auth);
106
+ return "active";
107
+ }
108
+ catch {
109
+ // Not an active member — check pending invitations
110
+ }
111
+ // Check if there's a pending invitation for this user
112
+ try {
113
+ const memberships = await githubApi("/user/memberships/orgs?state=pending&per_page=100", auth);
114
+ const pending = memberships.find((m) => m.organization.login.toLowerCase() === orgLogin.toLowerCase());
115
+ if (pending)
116
+ return "pending";
117
+ }
118
+ catch {
119
+ // Can't check pending — fall through
120
+ }
121
+ return "none";
122
+ }
123
+ /**
124
+ * Check whether the authenticated user can access a specific repo.
125
+ */
126
+ export async function checkRepoAccess(auth, orgLogin, repoName) {
127
+ try {
128
+ await githubApi(`/repos/${orgLogin}/${repoName}`, auth);
129
+ return true;
130
+ }
131
+ catch {
132
+ return false;
133
+ }
134
+ }
135
+ // ─── Invite message template ────────────────────────────────────────────────
136
+ /**
137
+ * Generate a ready-to-share invite message for the admin to send to the
138
+ * new member. Designed to be copy-pasted into Slack, email, or text.
139
+ */
140
+ export function formatInviteMessage(payload, token, memberEmail) {
141
+ const orgInviteUrl = `https://github.com/orgs/${payload.org}/invitation`;
142
+ const lines = [
143
+ `You've been invited to join ${payload.teamName} on HQ!`,
144
+ "",
145
+ ];
146
+ // Step 1: Accept org invite (which handles GitHub account creation too)
147
+ if (memberEmail) {
148
+ lines.push(`Step 1: Accept the GitHub invitation sent to ${memberEmail}`, ` (if you don't have a GitHub account yet, you'll be guided to create one)`, ` Direct link: ${orgInviteUrl}`, "");
149
+ }
150
+ else {
151
+ lines.push(`Step 1: Accept your GitHub organization invite`, ` Direct link: ${orgInviteUrl}`, ` (if you haven't received one, ask @${payload.invitedBy} to send it)`, "");
152
+ }
153
+ // Step 2: Install Node.js (platform-specific instructions)
154
+ lines.push(`Step 2: Install Node.js (if you don't have it already)`, "", ` Windows (PowerShell, run as Administrator):`, ` winget install OpenJS.NodeJS.LTS`, "", ` Mac (Terminal):`, ` brew install node`, ` (if you don't have brew: https://brew.sh)`, "", ` Or download from: https://nodejs.org`, "");
155
+ // Step 3: Single command with token
156
+ lines.push(`Step 3: Open your terminal and run this command:`, "", ` npx create-hq --invite ${token}`, "", ` Then follow the prompts to sign in with GitHub and complete setup.`, "", `---`, `Questions? Ask @${payload.invitedBy} or visit https://getindigo.ai/hq`);
157
+ return lines.join("\n");
158
+ }
159
+ /**
160
+ * Print the invite details to the console for the admin.
161
+ */
162
+ export function printInviteSummary(payload, token, _emailSent, memberEmail) {
163
+ console.log();
164
+ console.log(chalk.bold(" Invite ready!"));
165
+ console.log();
166
+ console.log(` ${chalk.dim("Team:")} ${chalk.cyan(payload.teamName)}`);
167
+ console.log(` ${chalk.dim("Org:")} ${payload.org}`);
168
+ if (memberEmail) {
169
+ console.log(` ${chalk.dim("Email:")} ${memberEmail}`);
170
+ }
171
+ console.log();
172
+ console.log(chalk.bold(" Invite code (share with the new member):"));
173
+ console.log();
174
+ console.log(` ${chalk.cyan(token)}`);
175
+ console.log();
176
+ console.log(chalk.dim(" Full invite message (copy-paste ready):"));
177
+ console.log(chalk.dim(" ─".repeat(30)));
178
+ const msg = formatInviteMessage(payload, token, memberEmail);
179
+ for (const line of msg.split("\n")) {
180
+ console.log(chalk.dim(" ") + line);
181
+ }
182
+ console.log(chalk.dim(" ─".repeat(30)));
183
+ console.log();
184
+ }
185
+ // ─── Mailto helper ──────────────────────────────────────────────────────────
186
+ /**
187
+ * Build a mailto: URL pre-populated with the invite message.
188
+ * Opens in the admin's default email client — they just hit Send.
189
+ */
190
+ export function buildMailtoUrl(payload, token, recipientEmail) {
191
+ const subject = `You're invited to join ${payload.teamName} on HQ`;
192
+ const body = formatInviteMessage(payload, token, recipientEmail);
193
+ return `mailto:${recipientEmail}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
194
+ }
195
+ /**
196
+ * Open the admin's email client with a pre-populated invite email.
197
+ */
198
+ export function openInviteEmail(payload, token, recipientEmail) {
199
+ const url = buildMailtoUrl(payload, token, recipientEmail);
200
+ openBrowser(url);
201
+ }
202
+ /**
203
+ * Copy text to the system clipboard. Cross-platform: pbcopy (macOS),
204
+ * clip (Windows), xclip/xsel (Linux). Returns true on success.
205
+ */
206
+ export function copyToClipboard(text) {
207
+ try {
208
+ const platform = process.platform;
209
+ if (platform === "darwin") {
210
+ execSync("pbcopy", { input: text });
211
+ }
212
+ else if (platform === "win32") {
213
+ execSync("clip", { input: text });
214
+ }
215
+ else {
216
+ // Try xclip first, fall back to xsel
217
+ try {
218
+ execSync("xclip -selection clipboard", { input: text });
219
+ }
220
+ catch {
221
+ execSync("xsel --clipboard --input", { input: text });
222
+ }
223
+ }
224
+ return true;
225
+ }
226
+ catch {
227
+ return false;
228
+ }
229
+ }
230
+ //# sourceMappingURL=invite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite.js","sourceRoot":"","sources":["../src/invite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Join-via-invite flow for HQ Teams members.
3
+ *
4
+ * When a member has an invite token (from an admin), this flow:
5
+ * 1. Decodes the token to get team coordinates
6
+ * 2. Authenticates via GitHub device flow
7
+ * 3. Checks org membership / repo access (waits if invite is pending)
8
+ * 4. Clones the team repo into companies/{slug}/
9
+ *
10
+ * This is the primary path for non-technical users who received an invite.
11
+ */
12
+ import { type GitHubAuth } from "./auth.js";
13
+ export interface JoinByInviteResult {
14
+ /** Team slug (companies/{slug}/ directory). */
15
+ slug: string;
16
+ /** Human-readable team name. */
17
+ teamName: string;
18
+ /** Local path where the team repo was cloned. */
19
+ companyDir: string;
20
+ /** GitHub HTML URL for the team repo. */
21
+ repoUrl: string;
22
+ }
23
+ /**
24
+ * Run the join-via-invite flow.
25
+ *
26
+ * @param auth - Authenticated GitHub user (already signed in)
27
+ * @param hqRoot - Local HQ root directory (where companies/ lives)
28
+ * @param token - The invite token string (hq_...) or raw base64
29
+ * @returns - Result on success, null on failure/abort
30
+ */
31
+ export declare function runJoinByInvite(auth: GitHubAuth, hqRoot: string, token: string): Promise<JoinByInviteResult | null>;
32
+ //# sourceMappingURL=join-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join-flow.d.ts","sourceRoot":"","sources":["../src/join-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAW5C,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;CACjB;AAwED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA6HpC"}