xtra-cli 1.0.4 → 1.0.5

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 (44) hide show
  1. package/dist/bin/xtra.js +2 -294
  2. package/dist/commands/access.js +1 -184
  3. package/dist/commands/admin.js +5 -118
  4. package/dist/commands/audit.js +1 -67
  5. package/dist/commands/branch.js +1 -212
  6. package/dist/commands/checkout.js +1 -80
  7. package/dist/commands/ci.js +31 -341
  8. package/dist/commands/completion.js +85 -224
  9. package/dist/commands/diff.js +6 -162
  10. package/dist/commands/doctor.js +2 -164
  11. package/dist/commands/env.js +2 -70
  12. package/dist/commands/export.js +2 -83
  13. package/dist/commands/generate.js +3 -179
  14. package/dist/commands/history.js +4 -77
  15. package/dist/commands/import.js +1 -121
  16. package/dist/commands/init.js +7 -205
  17. package/dist/commands/integration.js +11 -188
  18. package/dist/commands/jit-run.js +5 -0
  19. package/dist/commands/local.js +16 -198
  20. package/dist/commands/login.js +16 -198
  21. package/dist/commands/login.test.js +16 -51
  22. package/dist/commands/logout.js +1 -0
  23. package/dist/commands/logs.js +3 -121
  24. package/dist/commands/profile.js +14 -184
  25. package/dist/commands/project.js +1 -165
  26. package/dist/commands/rollback.js +1 -95
  27. package/dist/commands/rotate.js +3 -93
  28. package/dist/commands/run.js +11 -215
  29. package/dist/commands/scan.js +25 -127
  30. package/dist/commands/secrets.js +14 -305
  31. package/dist/commands/simulate.js +6 -109
  32. package/dist/commands/status.js +2 -93
  33. package/dist/commands/template.js +22 -276
  34. package/dist/commands/ui.js +2 -289
  35. package/dist/commands/watch.js +17 -123
  36. package/dist/lib/api.js +1 -187
  37. package/dist/lib/api.test.js +1 -89
  38. package/dist/lib/audit.js +1 -136
  39. package/dist/lib/config.js +1 -72
  40. package/dist/lib/config.test.js +1 -47
  41. package/dist/lib/crypto.js +1 -50
  42. package/dist/lib/manifest.js +1 -52
  43. package/dist/lib/profiles.js +1 -103
  44. package/package.json +2 -2
@@ -1,184 +1 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.accessCommand = void 0;
7
- const commander_1 = require("commander");
8
- const api_1 = require("../lib/api");
9
- const chalk_1 = __importDefault(require("chalk"));
10
- const ora_1 = __importDefault(require("ora"));
11
- const table_1 = require("table");
12
- const config_1 = require("../lib/config");
13
- const logAuditSafe = (event, projectId, meta) => {
14
- try {
15
- const { logAudit } = require("../lib/audit");
16
- logAudit(event, projectId, null, meta);
17
- }
18
- catch (e) { }
19
- };
20
- const safeError = (error) => error?.response?.data?.error || error?.message || "Unknown error";
21
- exports.accessCommand = new commander_1.Command("access")
22
- .description("Manage Just-in-Time access requests")
23
- .addCommand(new commander_1.Command("request")
24
- .description("Request access to a secret or project")
25
- .option("-p, --project <projectId>", "Project ID")
26
- .option("-s, --secret <secretId>", "Specific Secret ID (optional)")
27
- .requiredOption("-d, --duration <minutes>", "Duration in minutes")
28
- .requiredOption("-r, --reason <text>", "Reason for access")
29
- .action(async (options) => {
30
- let { project, secret, duration, reason } = options;
31
- if (!project) {
32
- project = (0, config_1.getRcConfig)().project;
33
- }
34
- if (!project) {
35
- console.error(chalk_1.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first."));
36
- process.exit(1);
37
- }
38
- const spinner = (0, ora_1.default)("Submitting access request...").start();
39
- try {
40
- const result = await api_1.api.requestAccess(project, reason, parseInt(duration), secret);
41
- spinner.succeed(chalk_1.default.green(`Access request submitted! (ID: ${result.requestId})`));
42
- console.log(chalk_1.default.yellow(`Status: ${result.status}`));
43
- // Audit log
44
- logAuditSafe("ACCESS_REQUESTED", project, { requestId: result.requestId, secretId: secret, duration, reason });
45
- }
46
- catch (error) {
47
- spinner.fail("Request failed");
48
- console.error(chalk_1.default.red(safeError(error)));
49
- }
50
- }))
51
- .addCommand(new commander_1.Command("list")
52
- .description("List access requests")
53
- .option("--pending", "Show pending approvals (for admins)", false)
54
- .action(async (options) => {
55
- try {
56
- const mode = options.pending ? "pending" : "my";
57
- const requests = await api_1.api.listAccessRequests(mode);
58
- if (requests.length === 0) {
59
- console.log(chalk_1.default.yellow("No requests found."));
60
- return;
61
- }
62
- const data = [
63
- [chalk_1.default.bold("ID"), chalk_1.default.bold("User"), chalk_1.default.bold("Target"), chalk_1.default.bold("Duration"), chalk_1.default.bold("Reason"), chalk_1.default.bold("Status")]
64
- ];
65
- requests.forEach((r) => {
66
- const target = r.secret ? `Secret: ${r.secret.key}` : `Project: ${r.projectId}`;
67
- data.push([
68
- r.id,
69
- r.user.email,
70
- target,
71
- `${r.duration}m`,
72
- r.reason,
73
- r.status === "pending" ? chalk_1.default.yellow(r.status) : r.status === "approved" ? chalk_1.default.green(r.status) : chalk_1.default.red(r.status)
74
- ]);
75
- });
76
- console.log((0, table_1.table)(data));
77
- }
78
- catch (error) {
79
- console.error(chalk_1.default.red("Failed to list requests: " + safeError(error)));
80
- }
81
- }))
82
- .addCommand(new commander_1.Command("approve")
83
- .description("Approve or reject a request")
84
- .argument("<requestId>", "Request ID")
85
- .requiredOption("--decision <decision>", "approved or rejected")
86
- .action(async (requestId, options) => {
87
- // Validate decision value
88
- const validDecisions = ["approved", "rejected"];
89
- if (!validDecisions.includes(options.decision.toLowerCase())) {
90
- console.error(chalk_1.default.red(`Invalid decision: '${options.decision}'. Must be 'approved' or 'rejected'.`));
91
- process.exit(1);
92
- }
93
- const spinner = (0, ora_1.default)("Processing decision...").start();
94
- try {
95
- const result = await api_1.api.approveAccess(requestId, options.decision);
96
- spinner.succeed(chalk_1.default.green(`Request ${options.decision}!`));
97
- if (result.expiresAt) {
98
- console.log(chalk_1.default.blue(`Access granted until: ${new Date(result.expiresAt).toLocaleString()}`));
99
- }
100
- // Audit log — privileged action
101
- logAuditSafe(options.decision === "approved" ? "ACCESS_APPROVED" : "ACCESS_REJECTED", null, { requestId, decision: options.decision, expiresAt: result.expiresAt });
102
- }
103
- catch (error) {
104
- spinner.fail("Operation failed");
105
- console.error(chalk_1.default.red(safeError(error)));
106
- }
107
- }))
108
- .addCommand(new commander_1.Command("jit-generate")
109
- .description("Generate a shareable JIT access link for a project")
110
- .option("-p, --project <projectId>", "Project ID")
111
- .requiredOption("-d, --duration <minutes>", "Access duration in minutes")
112
- .option("-b, --branch <branchId>", "Scope to branch ID")
113
- .option("-e, --env <environment>", "Scope to environment (production, staging, development)")
114
- .option("-s, --secrets <ids>", "Comma-separated secret IDs to scope access")
115
- .option("--label <text>", "Label for the JIT link")
116
- .option("--max-uses <count>", "Maximum number of uses", "1")
117
- .option("--expires <hours>", "Link expiry in hours", "24")
118
- .action(async (options) => {
119
- let { project, duration, branch, env, secrets, label, maxUses, expires } = options;
120
- if (!project) {
121
- project = (0, config_1.getRcConfig)().project;
122
- }
123
- if (!project) {
124
- console.error(chalk_1.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first."));
125
- process.exit(1);
126
- }
127
- const spinner = (0, ora_1.default)("Generating JIT link...").start();
128
- try {
129
- const opts = {
130
- projectId: project,
131
- duration: parseInt(duration),
132
- maxUses: parseInt(maxUses),
133
- expiresInHours: parseInt(expires),
134
- };
135
- if (branch)
136
- opts.branchId = branch;
137
- if (env)
138
- opts.environment = env;
139
- if (secrets)
140
- opts.secretIds = secrets.split(",").map((s) => s.trim());
141
- if (label)
142
- opts.label = label;
143
- const result = await api_1.api.generateJitLink(opts);
144
- spinner.succeed(chalk_1.default.green("JIT link generated!"));
145
- console.log();
146
- console.log(chalk_1.default.bold(" Shareable URL:"));
147
- console.log(chalk_1.default.cyan(` ${result.url}`));
148
- console.log();
149
- console.log(chalk_1.default.bold(" CLI Command:"));
150
- console.log(chalk_1.default.yellow(` ${result.cliCommand}`));
151
- console.log();
152
- console.log(chalk_1.default.dim(` Expires: ${new Date(result.expiresAt).toLocaleString()}`));
153
- console.log(chalk_1.default.dim(` Duration: ${result.duration} minutes | Access: ${result.accessLevel}-only`));
154
- logAuditSafe("JIT_LINK_GENERATED", project, { token: result.token, duration, env, branch });
155
- }
156
- catch (error) {
157
- spinner.fail("Failed to generate JIT link");
158
- console.error(chalk_1.default.red(safeError(error)));
159
- }
160
- }))
161
- .addCommand(new commander_1.Command("jit")
162
- .description("Claim a JIT access link (request read-only access)")
163
- .argument("<token>", "JIT link token")
164
- .action(async (token) => {
165
- const spinner = (0, ora_1.default)("Claiming JIT link...").start();
166
- try {
167
- // First, show link info
168
- const info = await api_1.api.getJitInfo(token);
169
- spinner.text = `Requesting access to "${info.projectName}"...`;
170
- const result = await api_1.api.claimJitLink(token);
171
- spinner.succeed(chalk_1.default.green("Access request submitted!"));
172
- console.log();
173
- console.log(chalk_1.default.yellow(" Status: Pending admin/owner approval"));
174
- console.log(chalk_1.default.dim(` Request ID: ${result.requestId}`));
175
- console.log(chalk_1.default.dim(` Access: ${result.accessLevel}-only for ${result.duration} minutes`));
176
- console.log();
177
- console.log(chalk_1.default.dim(" Run 'xtra access list' to check request status."));
178
- logAuditSafe("JIT_LINK_CLAIMED", null, { token, requestId: result.requestId });
179
- }
180
- catch (error) {
181
- spinner.fail("Failed to claim JIT link");
182
- console.error(chalk_1.default.red(safeError(error)));
183
- }
184
- }));
1
+ var ce=Object.create;var A=Object.defineProperty;var pe=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var ge=Object.getPrototypeOf,le=Object.prototype.hasOwnProperty;var C=(e,t)=>()=>(e&&(t=e(e=0)),t);var D=(e,t)=>{for(var s in t)A(e,s,{get:t[s],enumerable:!0})},G=(e,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of de(t))!le.call(e,r)&&r!==s&&A(e,r,{get:()=>t[r],enumerable:!(n=pe(t,r))||n.enumerable});return e};var p=(e,t,s)=>(s=e!=null?ce(ge(e)):{},G(t||!e||!e.__esModule?A(s,"default",{value:e,enumerable:!0}):s,e)),R=e=>G(A({},"__esModule",{value:!0}),e);var V={};D(V,{clearConfig:()=>ye,deleteConfig:()=>fe,getAuthToken:()=>J,getBreakGlassSession:()=>he,getConfig:()=>y,getConfigValue:()=>ue,getProjectConfig:()=>we,getRcConfig:()=>w,setBreakGlassSession:()=>b,setConfig:()=>me});var F,m,P,U,c,T,y,ue,me,ye,fe,J,he,b,we,w,x=C(()=>{F=p(require("conf")),m=p(require("fs")),P=p(require("path")),U="https://www.xtrasecurity.in/api",c=new F.default({projectName:"xtra-cli",defaults:{apiUrl:U}}),T=c.get("apiUrl");T&&!process.env.XTRA_API_URL&&(T.includes("localhost")||T.includes("xtra-security.vercel.app"))&&c.set("apiUrl",U);y=()=>({...c.store,apiUrl:process.env.XTRA_API_URL||c.get("apiUrl")||U}),ue=e=>c.get(e),me=(e,t)=>{if(c.set(e,t),e==="token"&&process.platform!=="win32"&&m.default.existsSync(c.path))try{m.default.chmodSync(c.path,384)}catch{}},ye=()=>c.clear(),fe=e=>c.delete(e),J=()=>c.get("token"),he=()=>c.get("breakGlassSessionId"),b=e=>{e?c.set("breakGlassSessionId",e):c.delete("breakGlassSessionId")},we=async()=>{try{let e=P.default.join(process.cwd(),"xtra.json");if(m.default.existsSync(e)){let t=m.default.readFileSync(e,"utf-8");return JSON.parse(t)}return null}catch{return null}},w=()=>{let e={};try{let t=P.default.join(process.cwd(),".xtrarc");m.default.existsSync(t)&&(e=JSON.parse(m.default.readFileSync(t,"utf-8")))}catch{}return{project:e.project||c.get("project")||"",env:e.env||c.get("env")||"development",branch:e.branch||c.get("branch")||"main"}}});var K,M,H,Ie,i,g,O=C(()=>{K=p(require("axios"));x();M=p(require("fs")),H=p(require("path")),Ie=JSON.parse(M.readFileSync(H.join(__dirname,"../../package.json"),"utf-8")),i=()=>{let{apiUrl:e}=y(),t=J();return K.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":Ie.version,...t?{Authorization:`Bearer ${t}`}:{}}})},g={login:async(e,t,s)=>(await i().post("/auth/cli-login",{email:e,password:t,apiKey:s})).data,getSecrets:async(e,t,s="main")=>(await i().get(`/projects/${e}/envs/${t}/secrets?branch=${s}`)).data,getSecretVersions:async(e,t,s="main")=>(await i().get(`/projects/${e}/envs/${t}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(e,t,s,n,r="main")=>(await i().post(`/projects/${e}/envs/${t}/secrets`,{secrets:s,expectedVersions:n,branch:r})).data,getSecretDetails:async(e,t,s,n="main")=>(await i().get(`/projects/${e}/envs/${t}/secrets/${s}?branch=${n}`)).data,syncLogs:async e=>(await i().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,t,s,n,r,a)=>(await i().post(`/projects/${e}/envs/${t}/secrets/link`,{key:s,sourceProjectId:n,sourceEnv:r,sourceKey:a})).data,rotateSecret:async(e,t,s,n,r)=>(await i().post(`/projects/${e}/envs/${t}/secrets/${s}/rotate`,{strategy:n,parsedNewValue:r})).data,promoteSecret:async(e,t,s)=>(await i().post(`/projects/${e}/envs/${t}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await i().get("/audit/verify")).data,exportAuditLogs:async(e,t,s,n)=>{let r={format:e};return t&&(r.startDate=t),s&&(r.endDate=s),n&&(r.projectId=n),(await i().post("/audit/export",r,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,t,s,n)=>(await i().post("/access/request",{projectId:e,secretId:n,reason:t,duration:s})).data,approveAccess:async(e,t)=>(await i().post("/access/approve",{requestId:e,decision:t})).data,listAccessRequests:async e=>{let{workspace:t}=y(),s=t?`&workspaceId=${t}`:"";return(await i().get(`/access/list?mode=${e}${s}`)).data},getAccessRequestStatus:async e=>(await i().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=y(),t=e?`/project?workspaceId=${e}`:"/project";return(await i().get(t)).data},getBranches:async e=>(await i().get(`/branch?projectId=${e}`)).data,createBranch:async(e,t,s)=>(await i().post("/branch",{projectId:e,name:t,description:s})).data,deleteBranch:async e=>(await i().delete(`/branch/${e}`)).data,updateBranch:async(e,t)=>(await i().put("/branch",{id:e,...t})).data,getRoles:async()=>(await i().get("/admin/roles")).data,getUsers:async e=>{let t=e?`?teamId=${e}`:"";return(await i().get(`/admin/users${t}`)).data},setUserRole:async(e,t,s)=>(await i().put("/admin/users/role",{email:e,role:t,teamId:s})).data,getIntegrationStatus:async e=>(await i().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await i().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await i().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,t)=>{let s=new URLSearchParams(t).toString();return(await i().get(`/projects/${e}/kubernetes?${s}`)).data},getSecretHistory:async(e,t,s)=>(await i().get(`/projects/${e}/envs/${t}/secrets/${s}/history`)).data,rollbackSecret:async(e,t,s,n)=>(await i().post(`/projects/${e}/envs/${t}/secrets/${s}/history`,{version:n})).data,cloneEnvironment:async(e,t,s,n,r)=>(await i().post(`/projects/${e}/envs/clone`,{fromEnv:t,toEnv:s,overwrite:n,branch:r})).data,generateJitLink:async e=>(await i().post("/jit/generate",e)).data,claimJitLink:async e=>(await i().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await i().get(`/jit/${e}`)).data,post:async(e,t)=>(await i().post(e,t)).data}});function W(){let e=z.get("masterKey");e||(e=I.default.randomBytes(32).toString("hex"),z.set("masterKey",e));let t=(0,Y.machineIdSync)();return I.default.createHash("sha256").update(e+t).digest()}var I,X,Y,Q,z,Z,ee,te=C(()=>{I=p(require("crypto")),X=p(require("conf")),Y=require("node-machine-id"),Q="aes-256-gcm",z=new X.default({projectName:"xtra-cli-crypto"});Z=e=>{let t=I.default.randomBytes(16),s=W(),n=I.default.createCipheriv(Q,s,t),r=n.update(e,"utf8","hex");r+=n.final("hex");let a=n.getAuthTag();return{iv:t.toString("hex"),content:r,tag:a.toString("hex")}},ee=e=>{let t=W(),s=Buffer.from(e.iv,"hex"),n=Buffer.from(e.tag,"hex"),r=I.default.createDecipheriv(Q,t,s);r.setAuthTag(n);let a=r.update(e.content,"hex","utf8");return a+=r.final("utf8"),a}});var re={};D(re,{loadAuditLogs:()=>L,logAudit:()=>Se,saveAuditLogs:()=>E,syncAuditLogs:()=>ve});function je(e){if(!e||typeof e!="object")return e;let t={...e},s=["password","token","secret","value","apiKey","secretValue"];for(let n of Object.keys(t))s.some(r=>n.toLowerCase().includes(r))&&(t[n]="[REDACTED]");return t}async function ne(e){try{if(!y().token)return!1;let s={action:e.action,entity:"cli-project",entityId:e.projectId||"global",details:je(e.details),timestamp:e.timestamp,projectId:e.projectId};return await g.post("/audit/cli-logs",{logs:[s]}),!0}catch(t){return process.env.DEBUG&&console.error("Failed to send audit log to backend:",t),!1}}function Se(e,t,s,n){let r={id:(0,se.v4)(),timestamp:new Date().toISOString(),action:e,projectId:t,environment:s,details:n,synced:!1},a=L();a.push(r),E(a),ne(r).then(d=>{if(d){r.synced=!0;let v=L(),k=v.findIndex($=>$.id===r.id);k!==-1&&(v[k].synced=!0,E(v))}}).catch(()=>{})}function L(){if(!j.default.existsSync(B))return[];try{let e=j.default.readFileSync(B,"utf-8"),t=JSON.parse(e),s=ee(t);return JSON.parse(s)}catch{return[]}}function E(e){j.default.existsSync(N)||j.default.mkdirSync(N,{recursive:!0});let t=JSON.stringify(e),s=Z(t);j.default.writeFileSync(B,JSON.stringify(s),"utf-8")}async function ve(){let e=L(),t=e.filter(n=>!n.synced);if(t.length===0)return 0;let s=0;for(let n of t)await ne(n)&&(n.synced=!0,s++);return s>0&&E(e),s}var j,_,se,N,B,oe=C(()=>{j=p(require("fs")),_=p(require("path")),se=require("uuid");te();x();O();N=_.default.join(process.cwd(),".xtra"),B=_.default.join(N,"audit.enc")});var xe={};D(xe,{accessCommand:()=>be});module.exports=R(xe);var l=require("commander");O();var o=p(require("chalk")),f=p(require("ora")),ie=require("table");x();var q=(e,t,s)=>{try{let{logAudit:n}=(oe(),R(re));n(e,t,null,s)}catch{}},S=e=>e?.response?.data?.error||e?.message||"Unknown error",be=new l.Command("access").description("Manage Just-in-Time access requests").addCommand(new l.Command("request").description("Request access to a secret or project").option("-p, --project <projectId>","Project ID").option("-s, --secret <secretId>","Specific Secret ID (optional)").requiredOption("-d, --duration <minutes>","Duration in minutes").requiredOption("-r, --reason <text>","Reason for access").action(async e=>{let{project:t,secret:s,duration:n,reason:r}=e;t||(t=w().project),t||(console.error(o.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1));let a=(0,f.default)("Submitting access request...").start();try{let d=await g.requestAccess(t,r,parseInt(n),s);a.succeed(o.default.green(`Access request submitted! (ID: ${d.requestId})`)),console.log(o.default.yellow(`Status: ${d.status}`)),q("ACCESS_REQUESTED",t,{requestId:d.requestId,secretId:s,duration:n,reason:r})}catch(d){a.fail("Request failed"),console.error(o.default.red(S(d)))}})).addCommand(new l.Command("list").description("List access requests").option("--pending","Show pending approvals (for admins)",!1).action(async e=>{try{let t=e.pending?"pending":"my",s=await g.listAccessRequests(t);if(s.length===0){console.log(o.default.yellow("No requests found."));return}let n=[[o.default.bold("ID"),o.default.bold("User"),o.default.bold("Target"),o.default.bold("Duration"),o.default.bold("Reason"),o.default.bold("Status")]];s.forEach(r=>{let a=r.secret?`Secret: ${r.secret.key}`:`Project: ${r.projectId}`;n.push([r.id,r.user.email,a,`${r.duration}m`,r.reason,r.status==="pending"?o.default.yellow(r.status):r.status==="approved"?o.default.green(r.status):o.default.red(r.status)])}),console.log((0,ie.table)(n))}catch(t){console.error(o.default.red("Failed to list requests: "+S(t)))}})).addCommand(new l.Command("approve").description("Approve or reject a request").argument("<requestId>","Request ID").requiredOption("--decision <decision>","approved or rejected").action(async(e,t)=>{["approved","rejected"].includes(t.decision.toLowerCase())||(console.error(o.default.red(`Invalid decision: '${t.decision}'. Must be 'approved' or 'rejected'.`)),process.exit(1));let n=(0,f.default)("Processing decision...").start();try{let r=await g.approveAccess(e,t.decision);n.succeed(o.default.green(`Request ${t.decision}!`)),r.expiresAt&&console.log(o.default.blue(`Access granted until: ${new Date(r.expiresAt).toLocaleString()}`)),q(t.decision==="approved"?"ACCESS_APPROVED":"ACCESS_REJECTED",null,{requestId:e,decision:t.decision,expiresAt:r.expiresAt})}catch(r){n.fail("Operation failed"),console.error(o.default.red(S(r)))}})).addCommand(new l.Command("jit-generate").description("Generate a shareable JIT access link for a project").option("-p, --project <projectId>","Project ID").requiredOption("-d, --duration <minutes>","Access duration in minutes").option("-b, --branch <branchId>","Scope to branch ID").option("-e, --env <environment>","Scope to environment (production, staging, development)").option("-s, --secrets <ids>","Comma-separated secret IDs to scope access").option("--label <text>","Label for the JIT link").option("--max-uses <count>","Maximum number of uses","1").option("--expires <hours>","Link expiry in hours","24").action(async e=>{let{project:t,duration:s,branch:n,env:r,secrets:a,label:d,maxUses:v,expires:k}=e;t||(t=w().project),t||(console.error(o.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1));let $=(0,f.default)("Generating JIT link...").start();try{let u={projectId:t,duration:parseInt(s),maxUses:parseInt(v),expiresInHours:parseInt(k)};n&&(u.branchId=n),r&&(u.environment=r),a&&(u.secretIds=a.split(",").map(ae=>ae.trim())),d&&(u.label=d);let h=await g.generateJitLink(u);$.succeed(o.default.green("JIT link generated!")),console.log(),console.log(o.default.bold(" Shareable URL:")),console.log(o.default.cyan(` ${h.url}`)),console.log(),console.log(o.default.bold(" CLI Command:")),console.log(o.default.yellow(` ${h.cliCommand}`)),console.log(),console.log(o.default.dim(` Expires: ${new Date(h.expiresAt).toLocaleString()}`)),console.log(o.default.dim(` Duration: ${h.duration} minutes | Access: ${h.accessLevel}-only`)),q("JIT_LINK_GENERATED",t,{token:h.token,duration:s,env:r,branch:n})}catch(u){$.fail("Failed to generate JIT link"),console.error(o.default.red(S(u)))}})).addCommand(new l.Command("jit").description("Claim a JIT access link (request read-only access)").argument("<token>","JIT link token").action(async e=>{let t=(0,f.default)("Claiming JIT link...").start();try{let s=await g.getJitInfo(e);t.text=`Requesting access to "${s.projectName}"...`;let n=await g.claimJitLink(e);t.succeed(o.default.green("Access request submitted!")),console.log(),console.log(o.default.yellow(" Status: Pending admin/owner approval")),console.log(o.default.dim(` Request ID: ${n.requestId}`)),console.log(o.default.dim(` Access: ${n.accessLevel}-only for ${n.duration} minutes`)),console.log(),console.log(o.default.dim(" Run 'xtra access list' to check request status.")),q("JIT_LINK_CLAIMED",null,{token:e,requestId:n.requestId})}catch(s){t.fail("Failed to claim JIT link"),console.error(o.default.red(S(s)))}})).addCommand(new l.Command("break-glass").description("Emergency break-glass access management").addCommand(new l.Command("link").description("Link an active break-glass session from the dashboard to this CLI").requiredOption("--id <sessionId>","Active Break Glass Session ID").action(async e=>{let{id:t}=e,s=(0,f.default)("Verifying session...").start();try{let n=await g.post("/access/break-glass",{projectId:w().project,reason:"CLI Link Verification"});(n.session||n.success)&&(b(t),s.succeed(o.default.red.bold("\u{1F6A8} EMERGENCY ACCESS LINKED")),console.log(),console.log(o.default.yellow(` Session ID: ${t}`)),console.log(o.default.dim(" Permissions: Full Administrative (Root)")),console.log(o.default.dim(" Audit Status: FULL VERBOSE LOGGING ENABLED")),console.log(),console.log(o.default.cyan(" You can now run any command with elevated permissions.")),console.log(o.default.cyan(" Example: 'xtra secrets list' will now show all secrets in the project.")))}catch(n){s.fail("Link failed"),console.error(o.default.red(S(n)))}})).addCommand(new l.Command("deactivate").description("End the current break-glass session").action(async()=>{let{getBreakGlassSession:e}=(x(),R(V));if(!e()){console.log(o.default.blue("No active break-glass session found locally."));return}let s=(0,f.default)("Deactivating session...").start();try{await g.post("/access/break-glass",{projectId:w().project,deactivate:!0}),b(null),s.succeed(o.default.green("Break-glass session ended."))}catch{b(null),s.warn("Local session cleared. (API might have already expired it)")}})));0&&(module.exports={accessCommand});
@@ -1,118 +1,5 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.adminCommand = void 0;
7
- const commander_1 = require("commander");
8
- const api_1 = require("../lib/api");
9
- const chalk_1 = __importDefault(require("chalk"));
10
- const ora_1 = __importDefault(require("ora"));
11
- const table_1 = require("table");
12
- exports.adminCommand = new commander_1.Command("admin")
13
- .description("Admin commands for user and role management");
14
- // Role Management
15
- const roleCommand = new commander_1.Command("role")
16
- .description("Manage user roles and permissions");
17
- const listRoles = async () => {
18
- const spinner = (0, ora_1.default)("Fetching roles from server...").start();
19
- try {
20
- const roles = await api_1.api.getRoles();
21
- spinner.stop();
22
- console.log(chalk_1.default.bold("\nAvailable Roles:\n"));
23
- const tableData = [
24
- [chalk_1.default.bold("Role"), chalk_1.default.bold("Description"), chalk_1.default.bold("Permissions")]
25
- ];
26
- roles.forEach((role) => {
27
- tableData.push([
28
- chalk_1.default.cyan(role.name),
29
- role.description || "-",
30
- Array.isArray(role.permissions) ? role.permissions.join(", ") : role.permissions || "-",
31
- ]);
32
- });
33
- console.log((0, table_1.table)(tableData));
34
- }
35
- catch (error) {
36
- spinner.fail("Failed to fetch roles");
37
- const safeErr = error.response?.data?.error || error.message || "Unknown error";
38
- console.error(chalk_1.default.red(safeErr));
39
- }
40
- };
41
- roleCommand
42
- .command("list")
43
- .description("List all available roles")
44
- .alias("ls")
45
- .action(listRoles);
46
- exports.adminCommand.addCommand(roleCommand);
47
- // Legacy/Short support: `xtra admin roles` -> alias to `xtra admin role list`
48
- exports.adminCommand
49
- .command("roles")
50
- .description("Alias for 'role list'")
51
- .action(listRoles);
52
- // List all users (admin only)
53
- exports.adminCommand
54
- .command("users")
55
- .description("List all users with their roles")
56
- .option("-t, --team <teamId>", "Filter by team ID")
57
- .action(async (options) => {
58
- const spinner = (0, ora_1.default)("Fetching users...").start();
59
- try {
60
- const users = await api_1.api.getUsers(options.team);
61
- spinner.stop();
62
- if (!users || users.length === 0) {
63
- console.log(chalk_1.default.yellow("No users found."));
64
- return;
65
- }
66
- console.log(chalk_1.default.bold("\nUsers:\n"));
67
- const tableData = [
68
- [chalk_1.default.bold("Email"), chalk_1.default.bold("Name"), chalk_1.default.bold("Role"), chalk_1.default.bold("Status")]
69
- ];
70
- users.forEach((user) => {
71
- const roleColor = user.role === "owner" || user.role === "admin"
72
- ? chalk_1.default.magenta
73
- : user.role === "viewer"
74
- ? chalk_1.default.gray
75
- : chalk_1.default.cyan;
76
- tableData.push([
77
- user.email,
78
- user.name || "-",
79
- roleColor(user.role),
80
- user.status || "active"
81
- ]);
82
- });
83
- console.log((0, table_1.table)(tableData));
84
- }
85
- catch (error) {
86
- spinner.fail("Failed to fetch users");
87
- console.error(chalk_1.default.red(error.message));
88
- }
89
- });
90
- // Set user role
91
- exports.adminCommand
92
- .command("set-role <email> <role>")
93
- .description("Change a user's role (owner, admin, developer, viewer, guest)")
94
- .option("-t, --team <teamId>", "Team ID (for team-specific role)")
95
- .action(async (email, role, options) => {
96
- const validRoles = ["owner", "admin", "developer", "viewer", "guest"];
97
- if (!validRoles.includes(role.toLowerCase())) {
98
- console.error(chalk_1.default.red(`Invalid role: ${role}`));
99
- console.log(chalk_1.default.yellow(`Valid roles: ${validRoles.join(", ")}`));
100
- process.exit(1);
101
- }
102
- const spinner = (0, ora_1.default)(`Updating role for ${email}...`).start();
103
- try {
104
- await api_1.api.setUserRole(email, role.toLowerCase(), options.team);
105
- spinner.succeed(chalk_1.default.green(`Role updated: ${email} → ${role}`));
106
- // Audit log this privileged action
107
- try {
108
- const { logAudit } = require("../lib/audit");
109
- logAudit("ADMIN_ROLE_CHANGE", null, null, { email, newRole: role, teamId: options.team });
110
- }
111
- catch (e) { }
112
- }
113
- catch (error) {
114
- spinner.fail("Failed to update role");
115
- const safeErr = error.response?.data?.error || error.message || "Unknown error";
116
- console.error(chalk_1.default.red(safeErr));
117
- }
118
- });
1
+ var te=Object.create;var f=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var ne=Object.getOwnPropertyNames;var re=Object.getPrototypeOf,oe=Object.prototype.hasOwnProperty;var h=(e,t)=>()=>(e&&(t=e(e=0)),t);var D=(e,t)=>{for(var s in t)f(e,s,{get:t[s],enumerable:!0})},E=(e,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ne(t))!oe.call(e,r)&&r!==s&&f(e,r,{get:()=>t[r],enumerable:!(n=se(t,r))||n.enumerable});return e};var c=(e,t,s)=>(s=e!=null?te(re(e)):{},E(t||!e||!e.__esModule?f(s,"default",{value:e,enumerable:!0}):s,e)),N=e=>E(f({},"__esModule",{value:!0}),e);var B,j,u,S,p,O,$=h(()=>{B=c(require("conf")),j="https://www.xtrasecurity.in/api",u=new B.default({projectName:"xtra-cli",defaults:{apiUrl:j}}),S=u.get("apiUrl");S&&!process.env.XTRA_API_URL&&(S.includes("localhost")||S.includes("xtra-security.vercel.app"))&&u.set("apiUrl",j);p=()=>({...u.store,apiUrl:process.env.XTRA_API_URL||u.get("apiUrl")||j}),O=()=>u.get("token")});var T,_,F,ae,o,g,k=h(()=>{T=c(require("axios"));$();_=c(require("fs")),F=c(require("path")),ae=JSON.parse(_.readFileSync(F.join(__dirname,"../../package.json"),"utf-8")),o=()=>{let{apiUrl:e}=p(),t=O();return T.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":ae.version,...t?{Authorization:`Bearer ${t}`}:{}}})},g={login:async(e,t,s)=>(await o().post("/auth/cli-login",{email:e,password:t,apiKey:s})).data,getSecrets:async(e,t,s="main")=>(await o().get(`/projects/${e}/envs/${t}/secrets?branch=${s}`)).data,getSecretVersions:async(e,t,s="main")=>(await o().get(`/projects/${e}/envs/${t}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(e,t,s,n,r="main")=>(await o().post(`/projects/${e}/envs/${t}/secrets`,{secrets:s,expectedVersions:n,branch:r})).data,getSecretDetails:async(e,t,s,n="main")=>(await o().get(`/projects/${e}/envs/${t}/secrets/${s}?branch=${n}`)).data,syncLogs:async e=>(await o().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,t,s,n,r,a)=>(await o().post(`/projects/${e}/envs/${t}/secrets/link`,{key:s,sourceProjectId:n,sourceEnv:r,sourceKey:a})).data,rotateSecret:async(e,t,s,n,r)=>(await o().post(`/projects/${e}/envs/${t}/secrets/${s}/rotate`,{strategy:n,parsedNewValue:r})).data,promoteSecret:async(e,t,s)=>(await o().post(`/projects/${e}/envs/${t}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await o().get("/audit/verify")).data,exportAuditLogs:async(e,t,s,n)=>{let r={format:e};return t&&(r.startDate=t),s&&(r.endDate=s),n&&(r.projectId=n),(await o().post("/audit/export",r,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,t,s,n)=>(await o().post("/access/request",{projectId:e,secretId:n,reason:t,duration:s})).data,approveAccess:async(e,t)=>(await o().post("/access/approve",{requestId:e,decision:t})).data,listAccessRequests:async e=>{let{workspace:t}=p(),s=t?`&workspaceId=${t}`:"";return(await o().get(`/access/list?mode=${e}${s}`)).data},getAccessRequestStatus:async e=>(await o().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=p(),t=e?`/project?workspaceId=${e}`:"/project";return(await o().get(t)).data},getBranches:async e=>(await o().get(`/branch?projectId=${e}`)).data,createBranch:async(e,t,s)=>(await o().post("/branch",{projectId:e,name:t,description:s})).data,deleteBranch:async e=>(await o().delete(`/branch/${e}`)).data,updateBranch:async(e,t)=>(await o().put("/branch",{id:e,...t})).data,getRoles:async()=>(await o().get("/admin/roles")).data,getUsers:async e=>{let t=e?`?teamId=${e}`:"";return(await o().get(`/admin/users${t}`)).data},setUserRole:async(e,t,s)=>(await o().put("/admin/users/role",{email:e,role:t,teamId:s})).data,getIntegrationStatus:async e=>(await o().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await o().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await o().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,t)=>{let s=new URLSearchParams(t).toString();return(await o().get(`/projects/${e}/kubernetes?${s}`)).data},getSecretHistory:async(e,t,s)=>(await o().get(`/projects/${e}/envs/${t}/secrets/${s}/history`)).data,rollbackSecret:async(e,t,s,n)=>(await o().post(`/projects/${e}/envs/${t}/secrets/${s}/history`,{version:n})).data,cloneEnvironment:async(e,t,s,n,r)=>(await o().post(`/projects/${e}/envs/clone`,{fromEnv:t,toEnv:s,overwrite:n,branch:r})).data,generateJitLink:async e=>(await o().post("/jit/generate",e)).data,claimJitLink:async e=>(await o().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await o().get(`/jit/${e}`)).data,post:async(e,t)=>(await o().post(e,t)).data}});function K(){let e=P.get("masterKey");e||(e=d.default.randomBytes(32).toString("hex"),P.set("masterKey",e));let t=(0,G.machineIdSync)();return d.default.createHash("sha256").update(e+t).digest()}var d,J,G,q,P,V,H,z=h(()=>{d=c(require("crypto")),J=c(require("conf")),G=require("node-machine-id"),q="aes-256-gcm",P=new J.default({projectName:"xtra-cli-crypto"});V=e=>{let t=d.default.randomBytes(16),s=K(),n=d.default.createCipheriv(q,s,t),r=n.update(e,"utf8","hex");r+=n.final("hex");let a=n.getAuthTag();return{iv:t.toString("hex"),content:r,tag:a.toString("hex")}},H=e=>{let t=K(),s=Buffer.from(e.iv,"hex"),n=Buffer.from(e.tag,"hex"),r=d.default.createDecipheriv(q,t,s);r.setAuthTag(n);let a=r.update(e.content,"hex","utf8");return a+=r.final("utf8"),a}});var Q={};D(Q,{loadAuditLogs:()=>w,logAudit:()=>ce,saveAuditLogs:()=>v,syncAuditLogs:()=>pe});function ie(e){if(!e||typeof e!="object")return e;let t={...e},s=["password","token","secret","value","apiKey","secretValue"];for(let n of Object.keys(t))s.some(r=>n.toLowerCase().includes(r))&&(t[n]="[REDACTED]");return t}async function X(e){try{if(!p().token)return!1;let s={action:e.action,entity:"cli-project",entityId:e.projectId||"global",details:ie(e.details),timestamp:e.timestamp,projectId:e.projectId};return await g.post("/audit/cli-logs",{logs:[s]}),!0}catch(t){return process.env.DEBUG&&console.error("Failed to send audit log to backend:",t),!1}}function ce(e,t,s,n){let r={id:(0,M.v4)(),timestamp:new Date().toISOString(),action:e,projectId:t,environment:s,details:n,synced:!1},a=w();a.push(r),v(a),X(r).then(y=>{if(y){r.synced=!0;let x=w(),L=x.findIndex(ee=>ee.id===r.id);L!==-1&&(x[L].synced=!0,v(x))}}).catch(()=>{})}function w(){if(!l.default.existsSync(A))return[];try{let e=l.default.readFileSync(A,"utf-8"),t=JSON.parse(e),s=H(t);return JSON.parse(s)}catch{return[]}}function v(e){l.default.existsSync(I)||l.default.mkdirSync(I,{recursive:!0});let t=JSON.stringify(e),s=V(t);l.default.writeFileSync(A,JSON.stringify(s),"utf-8")}async function pe(){let e=w(),t=e.filter(n=>!n.synced);if(t.length===0)return 0;let s=0;for(let n of t)await X(n)&&(n.synced=!0,s++);return s>0&&v(e),s}var l,C,M,I,A,W=h(()=>{l=c(require("fs")),C=c(require("path")),M=require("uuid");z();$();k();I=C.default.join(process.cwd(),".xtra"),A=C.default.join(I,"audit.enc")});var ge={};D(ge,{adminCommand:()=>m});module.exports=N(ge);var R=require("commander");k();var i=c(require("chalk")),b=c(require("ora")),U=require("table"),m=new R.Command("admin").description("Admin commands for user and role management"),Y=new R.Command("role").description("Manage user roles and permissions"),Z=async()=>{let e=(0,b.default)("Fetching roles from server...").start();try{let t=await g.getRoles();e.stop(),console.log(i.default.bold(`
2
+ Available Roles:
3
+ `));let s=[[i.default.bold("Role"),i.default.bold("Description"),i.default.bold("Permissions")]];t.forEach(n=>{s.push([i.default.cyan(n.name),n.description||"-",Array.isArray(n.permissions)?n.permissions.join(", "):n.permissions||"-"])}),console.log((0,U.table)(s))}catch(t){e.fail("Failed to fetch roles");let s=t.response?.data?.error||t.message||"Unknown error";console.error(i.default.red(s))}};Y.command("list").description("List all available roles").alias("ls").action(Z);m.addCommand(Y);m.command("roles").description("Alias for 'role list'").action(Z);m.command("users").description("List all users with their roles").option("-t, --team <teamId>","Filter by team ID").action(async e=>{let t=(0,b.default)("Fetching users...").start();try{let s=await g.getUsers(e.team);if(t.stop(),!s||s.length===0){console.log(i.default.yellow("No users found."));return}console.log(i.default.bold(`
4
+ Users:
5
+ `));let n=[[i.default.bold("Email"),i.default.bold("Name"),i.default.bold("Role"),i.default.bold("Status")]];s.forEach(r=>{let a=r.role==="owner"||r.role==="admin"?i.default.magenta:r.role==="viewer"?i.default.gray:i.default.cyan;n.push([r.email,r.name||"-",a(r.role),r.status||"active"])}),console.log((0,U.table)(n))}catch(s){t.fail("Failed to fetch users"),console.error(i.default.red(s.message))}});m.command("set-role <email> <role>").description("Change a user's role (owner, admin, developer, viewer, guest)").option("-t, --team <teamId>","Team ID (for team-specific role)").action(async(e,t,s)=>{let n=["owner","admin","developer","viewer","guest"];n.includes(t.toLowerCase())||(console.error(i.default.red(`Invalid role: ${t}`)),console.log(i.default.yellow(`Valid roles: ${n.join(", ")}`)),process.exit(1));let r=(0,b.default)(`Updating role for ${e}...`).start();try{await g.setUserRole(e,t.toLowerCase(),s.team),r.succeed(i.default.green(`Role updated: ${e} \u2192 ${t}`));try{let{logAudit:a}=(W(),N(Q));a("ADMIN_ROLE_CHANGE",null,null,{email:e,newRole:t,teamId:s.team})}catch{}}catch(a){r.fail("Failed to update role");let y=a.response?.data?.error||a.message||"Unknown error";console.error(i.default.red(y))}});0&&(module.exports={adminCommand});
@@ -1,67 +1 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.auditCommand = void 0;
7
- const commander_1 = require("commander");
8
- const api_1 = require("../lib/api");
9
- const chalk_1 = __importDefault(require("chalk"));
10
- const ora_1 = __importDefault(require("ora"));
11
- const fs_1 = __importDefault(require("fs"));
12
- exports.auditCommand = new commander_1.Command("audit")
13
- .description("Manage and verify audit logs")
14
- // Subcommand: Verify
15
- .addCommand(new commander_1.Command("verify")
16
- .description("Verify the integrity of the audit log chain (Tamper-Evident)")
17
- .action(async () => {
18
- const spinner = (0, ora_1.default)("Verifying audit chain integrity...").start();
19
- try {
20
- const result = await api_1.api.verifyAuditLogs();
21
- if (result.valid) {
22
- spinner.succeed(chalk_1.default.green(result.message));
23
- }
24
- else {
25
- spinner.fail(chalk_1.default.red("Verification Failed!"));
26
- console.error(chalk_1.default.red(`Broken at Log ID: ${result.details?.brokenAtId}`));
27
- console.error(chalk_1.default.red(`Reason: ${result.details?.reason}`));
28
- }
29
- }
30
- catch (error) {
31
- spinner.fail("Verification failed");
32
- if (error.response?.data?.details) {
33
- console.error(chalk_1.default.red(`Chain Broken: ${error.response.data.message}`));
34
- console.error(chalk_1.default.yellow(`Details: ${JSON.stringify(error.response.data.details, null, 2)}`));
35
- }
36
- else {
37
- console.error(chalk_1.default.red(error.message));
38
- }
39
- }
40
- }))
41
- // Subcommand: Export
42
- .addCommand(new commander_1.Command("export")
43
- .description("Export audit logs for compliance (SOC2/ISO)")
44
- .option("-f, --format <format>", "Output format (json, csv)", "json")
45
- .option("--start <date>", "Start date (YYYY-MM-DD)")
46
- .option("--end <date>", "End date (YYYY-MM-DD)")
47
- .option("-o, --output <file>", "Output file path")
48
- .action(async (options) => {
49
- const { format, start, end, output } = options;
50
- const spinner = (0, ora_1.default)(`Exporting audit logs (${format})...`).start();
51
- try {
52
- const data = await api_1.api.exportAuditLogs(format, start, end);
53
- const content = typeof data === 'object' ? JSON.stringify(data, null, 2) : data;
54
- if (output) {
55
- fs_1.default.writeFileSync(output, content);
56
- spinner.succeed(chalk_1.default.green(`Export saved to ${output}`));
57
- }
58
- else {
59
- spinner.stop();
60
- console.log(content);
61
- }
62
- }
63
- catch (error) {
64
- spinner.fail("Export failed");
65
- console.error(chalk_1.default.red(error.message));
66
- }
67
- }));
1
+ var I=Object.create;var d=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var R=Object.getPrototypeOf,U=Object.prototype.hasOwnProperty;var L=(e,t)=>{for(var s in t)d(e,s,{get:t[s],enumerable:!0})},$=(e,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of A(t))!U.call(e,o)&&o!==s&&d(e,o,{get:()=>t[o],enumerable:!(n=C(t,o))||n.enumerable});return e};var c=(e,t,s)=>(s=e!=null?I(R(e)):{},$(t||!e||!e.__esModule?d(s,"default",{value:e,enumerable:!0}):s,e)),O=e=>$(d({},"__esModule",{value:!0}),e);var D={};L(D,{auditCommand:()=>_});module.exports=O(D);var u=require("commander");var v=c(require("axios"));var S=c(require("conf"));var m="https://www.xtrasecurity.in/api",g=new S.default({projectName:"xtra-cli",defaults:{apiUrl:m}}),y=g.get("apiUrl");y&&!process.env.XTRA_API_URL&&(y.includes("localhost")||y.includes("xtra-security.vercel.app"))&&g.set("apiUrl",m);var l=()=>({...g.store,apiUrl:process.env.XTRA_API_URL||g.get("apiUrl")||m});var j=()=>g.get("token");var x=c(require("fs")),b=c(require("path")),P=JSON.parse(x.readFileSync(b.join(__dirname,"../../package.json"),"utf-8")),r=()=>{let{apiUrl:e}=l(),t=j();return v.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":P.version,...t?{Authorization:`Bearer ${t}`}:{}}})},f={login:async(e,t,s)=>(await r().post("/auth/cli-login",{email:e,password:t,apiKey:s})).data,getSecrets:async(e,t,s="main")=>(await r().get(`/projects/${e}/envs/${t}/secrets?branch=${s}`)).data,getSecretVersions:async(e,t,s="main")=>(await r().get(`/projects/${e}/envs/${t}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(e,t,s,n,o="main")=>(await r().post(`/projects/${e}/envs/${t}/secrets`,{secrets:s,expectedVersions:n,branch:o})).data,getSecretDetails:async(e,t,s,n="main")=>(await r().get(`/projects/${e}/envs/${t}/secrets/${s}?branch=${n}`)).data,syncLogs:async e=>(await r().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,t,s,n,o,i)=>(await r().post(`/projects/${e}/envs/${t}/secrets/link`,{key:s,sourceProjectId:n,sourceEnv:o,sourceKey:i})).data,rotateSecret:async(e,t,s,n,o)=>(await r().post(`/projects/${e}/envs/${t}/secrets/${s}/rotate`,{strategy:n,parsedNewValue:o})).data,promoteSecret:async(e,t,s)=>(await r().post(`/projects/${e}/envs/${t}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await r().get("/audit/verify")).data,exportAuditLogs:async(e,t,s,n)=>{let o={format:e};return t&&(o.startDate=t),s&&(o.endDate=s),n&&(o.projectId=n),(await r().post("/audit/export",o,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,t,s,n)=>(await r().post("/access/request",{projectId:e,secretId:n,reason:t,duration:s})).data,approveAccess:async(e,t)=>(await r().post("/access/approve",{requestId:e,decision:t})).data,listAccessRequests:async e=>{let{workspace:t}=l(),s=t?`&workspaceId=${t}`:"";return(await r().get(`/access/list?mode=${e}${s}`)).data},getAccessRequestStatus:async e=>(await r().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=l(),t=e?`/project?workspaceId=${e}`:"/project";return(await r().get(t)).data},getBranches:async e=>(await r().get(`/branch?projectId=${e}`)).data,createBranch:async(e,t,s)=>(await r().post("/branch",{projectId:e,name:t,description:s})).data,deleteBranch:async e=>(await r().delete(`/branch/${e}`)).data,updateBranch:async(e,t)=>(await r().put("/branch",{id:e,...t})).data,getRoles:async()=>(await r().get("/admin/roles")).data,getUsers:async e=>{let t=e?`?teamId=${e}`:"";return(await r().get(`/admin/users${t}`)).data},setUserRole:async(e,t,s)=>(await r().put("/admin/users/role",{email:e,role:t,teamId:s})).data,getIntegrationStatus:async e=>(await r().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await r().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await r().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,t)=>{let s=new URLSearchParams(t).toString();return(await r().get(`/projects/${e}/kubernetes?${s}`)).data},getSecretHistory:async(e,t,s)=>(await r().get(`/projects/${e}/envs/${t}/secrets/${s}/history`)).data,rollbackSecret:async(e,t,s,n)=>(await r().post(`/projects/${e}/envs/${t}/secrets/${s}/history`,{version:n})).data,cloneEnvironment:async(e,t,s,n,o)=>(await r().post(`/projects/${e}/envs/clone`,{fromEnv:t,toEnv:s,overwrite:n,branch:o})).data,generateJitLink:async e=>(await r().post("/jit/generate",e)).data,claimJitLink:async e=>(await r().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await r().get(`/jit/${e}`)).data,post:async(e,t)=>(await r().post(e,t)).data};var a=c(require("chalk")),w=c(require("ora")),k=c(require("fs")),_=new u.Command("audit").description("Manage and verify audit logs").addCommand(new u.Command("verify").description("Verify the integrity of the audit log chain (Tamper-Evident)").action(async()=>{let e=(0,w.default)("Verifying audit chain integrity...").start();try{let t=await f.verifyAuditLogs();t.valid?e.succeed(a.default.green(t.message)):(e.fail(a.default.red("Verification Failed!")),console.error(a.default.red(`Broken at Log ID: ${t.details?.brokenAtId}`)),console.error(a.default.red(`Reason: ${t.details?.reason}`)))}catch(t){e.fail("Verification failed"),t.response?.data?.details?(console.error(a.default.red(`Chain Broken: ${t.response.data.message}`)),console.error(a.default.yellow(`Details: ${JSON.stringify(t.response.data.details,null,2)}`))):console.error(a.default.red(t.message))}})).addCommand(new u.Command("export").description("Export audit logs for compliance (SOC2/ISO)").option("-f, --format <format>","Output format (json, csv)","json").option("--start <date>","Start date (YYYY-MM-DD)").option("--end <date>","End date (YYYY-MM-DD)").option("-o, --output <file>","Output file path").action(async e=>{let{format:t,start:s,end:n,output:o}=e,i=(0,w.default)(`Exporting audit logs (${t})...`).start();try{let p=await f.exportAuditLogs(t,s,n),h=typeof p=="object"?JSON.stringify(p,null,2):p;o?(k.default.writeFileSync(o,h),i.succeed(a.default.green(`Export saved to ${o}`))):(i.stop(),console.log(h))}catch(p){i.fail("Export failed"),console.error(a.default.red(p.message))}}));0&&(module.exports={auditCommand});