repowisestage 0.0.26 → 0.0.27

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 (2) hide show
  1. package/dist/bin/repowise.js +134 -10
  2. package/package.json +1 -1
@@ -1831,6 +1831,101 @@ import { dirname as dirname6, join as join18 } from "path";
1831
1831
  import chalk5 from "chalk";
1832
1832
  import ora from "ora";
1833
1833
 
1834
+ // ../../packages/shared/src/constants/tiers.ts
1835
+ var SUBSCRIPTION_TIERS = {
1836
+ STARTER: "starter",
1837
+ PRO: "pro",
1838
+ TEAM: "team"
1839
+ };
1840
+ var TIER_LIMITS = {
1841
+ [SUBSCRIPTION_TIERS.STARTER]: {
1842
+ maxRepos: 1,
1843
+ maxSeats: 1,
1844
+ maxSyncsPerMonth: 10,
1845
+ maxConcurrentSyncs: 1,
1846
+ bedrockEndpoint: "public"
1847
+ },
1848
+ [SUBSCRIPTION_TIERS.PRO]: {
1849
+ maxRepos: 2,
1850
+ maxSeats: 1,
1851
+ maxSyncsPerMonth: 30,
1852
+ maxConcurrentSyncs: 2,
1853
+ bedrockEndpoint: "public"
1854
+ },
1855
+ [SUBSCRIPTION_TIERS.TEAM]: {
1856
+ maxRepos: 3,
1857
+ maxSeats: 999999,
1858
+ maxSyncsPerMonth: 30,
1859
+ maxConcurrentSyncs: 10,
1860
+ bedrockEndpoint: "public"
1861
+ }
1862
+ };
1863
+
1864
+ // ../../packages/shared/src/constants/roles.ts
1865
+ var ROLES = {
1866
+ OWNER: "owner",
1867
+ ADMIN: "admin",
1868
+ REPO_MANAGER: "repo_manager",
1869
+ MEMBER: "member"
1870
+ };
1871
+ var PERMISSIONS = {
1872
+ [ROLES.OWNER]: {
1873
+ connectRepos: true,
1874
+ viewSync: true,
1875
+ triggerRetry: true,
1876
+ configWatcher: true,
1877
+ inviteMembers: true,
1878
+ manageBilling: true,
1879
+ configAiTools: true,
1880
+ manageTeam: true
1881
+ },
1882
+ [ROLES.ADMIN]: {
1883
+ connectRepos: true,
1884
+ viewSync: true,
1885
+ triggerRetry: true,
1886
+ configWatcher: true,
1887
+ inviteMembers: true,
1888
+ manageBilling: false,
1889
+ configAiTools: true,
1890
+ manageTeam: true
1891
+ },
1892
+ [ROLES.REPO_MANAGER]: {
1893
+ connectRepos: true,
1894
+ viewSync: true,
1895
+ triggerRetry: true,
1896
+ configWatcher: true,
1897
+ inviteMembers: false,
1898
+ manageBilling: false,
1899
+ configAiTools: true,
1900
+ manageTeam: false
1901
+ },
1902
+ [ROLES.MEMBER]: {
1903
+ connectRepos: false,
1904
+ viewSync: true,
1905
+ triggerRetry: true,
1906
+ configWatcher: false,
1907
+ inviteMembers: false,
1908
+ manageBilling: false,
1909
+ configAiTools: true,
1910
+ manageTeam: false
1911
+ }
1912
+ };
1913
+ function hasPermission(role, permission) {
1914
+ return PERMISSIONS[role][permission];
1915
+ }
1916
+ var ROLE_PRIORITY = [
1917
+ ROLES.OWNER,
1918
+ ROLES.ADMIN,
1919
+ ROLES.REPO_MANAGER,
1920
+ ROLES.MEMBER
1921
+ ];
1922
+ function resolveRole(groups) {
1923
+ for (const role of ROLE_PRIORITY) {
1924
+ if (groups.includes(role)) return role;
1925
+ }
1926
+ return ROLES.MEMBER;
1927
+ }
1928
+
1834
1929
  // src/lib/auth.ts
1835
1930
  import { createHash, randomBytes } from "crypto";
1836
1931
  import { readFile as readFile7, writeFile as writeFile9, mkdir as mkdir9, chmod as chmod4, unlink as unlink7 } from "fs/promises";
@@ -2110,7 +2205,11 @@ function decodeIdToken(idToken) {
2110
2205
  const parts = idToken.split(".");
2111
2206
  if (parts.length < 2) return { email: "unknown" };
2112
2207
  const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
2113
- return { email: payload.email ?? "unknown", tenantId: payload["custom:tenant_id"] };
2208
+ return {
2209
+ email: payload.email ?? "unknown",
2210
+ tenantId: payload["custom:tenant_id"],
2211
+ groups: payload["cognito:groups"]
2212
+ };
2114
2213
  } catch {
2115
2214
  return { email: "unknown" };
2116
2215
  }
@@ -2922,26 +3021,51 @@ async function create() {
2922
3021
  try {
2923
3022
  const pricing = await apiRequest(`/v1/repos/${repoId}/rescan-pricing`);
2924
3023
  if (pricing.lastFullScanAt) {
2925
- if (pricing.allowed && pricing.isFree) {
2926
- spinner.succeed(chalk5.cyan("Free rescan available. Will trigger a full rescan."));
2927
- useFreeRescan = true;
2928
- } else {
3024
+ const { groups } = decodeIdToken(credentials.idToken);
3025
+ const role = resolveRole(groups ?? []);
3026
+ const canRescan = hasPermission(role, "connectRepos");
3027
+ if (!canRescan) {
2929
3028
  spinner.fail(chalk5.red("This repository already has context generated."));
2930
3029
  console.log(
2931
3030
  chalk5.cyan(
2932
3031
  `
2933
- If you're a team member, run: ${chalk5.bold("repowise member")}
3032
+ As a team member, run: ${chalk5.bold("repowise member")}
2934
3033
  This will download context and configure your AI tools.
2935
3034
  `
2936
3035
  )
2937
3036
  );
3037
+ process.exitCode = 1;
3038
+ return;
3039
+ }
3040
+ if (pricing.allowed && pricing.isFree) {
3041
+ spinner.succeed(chalk5.cyan("Free rescan available. Will trigger a full rescan."));
3042
+ useFreeRescan = true;
3043
+ } else if (pricing.allowed) {
3044
+ spinner.stop();
3045
+ const costText = pricing.estimatedCost && pricing.estimatedCost > 0 ? `$${pricing.estimatedCost.toFixed(2)}` : "pay-as-you-go (based on actual processing cost)";
2938
3046
  console.log(
2939
- chalk5.dim(
2940
- ` To trigger a new full scan, visit: https://app.repowise.ai/repos/${repoId}
2941
- To sync recent changes, use: repowise sync
2942
- `
3047
+ chalk5.yellow(
3048
+ `
3049
+ This repository already has context generated.
3050
+ A full rescan will cost: ${chalk5.bold(costText)}`
2943
3051
  )
2944
3052
  );
3053
+ if (pricing.costWarning) {
3054
+ console.log(chalk5.dim(` ${pricing.costWarning}`));
3055
+ }
3056
+ const { confirm: confirm2 } = await import("@inquirer/prompts");
3057
+ const proceed = await confirm2({
3058
+ message: "Proceed with paid full rescan?",
3059
+ default: false
3060
+ });
3061
+ if (!proceed) {
3062
+ console.log(chalk5.dim("\n To sync recent changes, use: repowise sync\n"));
3063
+ process.exitCode = 0;
3064
+ return;
3065
+ }
3066
+ useFreeRescan = true;
3067
+ } else {
3068
+ spinner.fail(chalk5.red(pricing.reason ?? "Cannot rescan at this time."));
2945
3069
  process.exitCode = 1;
2946
3070
  return;
2947
3071
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repowisestage",
3
- "version": "0.0.26",
3
+ "version": "0.0.27",
4
4
  "type": "module",
5
5
  "description": "AI-optimized codebase context generator",
6
6
  "bin": {