legacyver 2.1.5 → 2.1.7

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "legacyver",
3
- "version": "2.1.5",
3
+ "version": "2.1.7",
4
4
  "description": "AI-powered CLI tool to auto-generate technical documentation from legacy/undocumented codebases",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/api/auth.js CHANGED
@@ -1,69 +1,69 @@
1
1
  'use strict';
2
2
 
3
+ const crypto = require('crypto');
3
4
  const { Pool } = require('pg');
4
5
  const dbConfig = require('../db/config');
5
6
 
6
7
  /**
7
- * Find or create a user by email.
8
- * Direct DB approach no web API dependency.
9
- * @param {string} email
10
- * @param {string} username
8
+ * Validate a CLI session token against app.user_sessions.
9
+ * Returns user info if valid, null if expired/revoked/not found.
10
+ *
11
+ * @param {string} token raw token from ~/.legacyver/session.json
11
12
  * @param {object} [opts] optional overrides for testing
12
- * @param {object} [opts.pool] pg Pool instance (skips internal pool creation)
13
- * @returns {Promise<{userId: string, username: string, email: string, isNew: boolean}>}
13
+ * @param {object} [opts.pool] pg Pool instance
14
+ * @returns {Promise<{userId: string, username: string, email: string} | null>}
14
15
  */
15
- async function loginOrRegister(email, username, opts) {
16
+ async function validateToken(token, opts) {
17
+ if (!token) return null;
18
+
16
19
  const ownPool = !(opts && opts.pool);
17
20
  const pool = (opts && opts.pool) || new Pool(dbConfig);
18
21
  try {
19
- // Try to find existing user by email
20
- const existing = await pool.query(
21
- 'SELECT id, username, email FROM users WHERE email = $1',
22
- [email]
23
- );
22
+ const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
24
23
 
25
- if (existing.rows.length > 0) {
26
- const user = existing.rows[0];
27
- // Update login_status
28
- await pool.query('UPDATE users SET login_status = true WHERE id = $1', [user.id]);
29
- return { userId: user.id, username: user.username, email: user.email, isNew: false };
30
- }
31
-
32
- // Check if username is taken
33
- const usernameCheck = await pool.query(
34
- 'SELECT id FROM users WHERE username = $1',
35
- [username]
24
+ const result = await pool.query(
25
+ `SELECT s.user_id, u.username, u.email
26
+ FROM app.user_sessions s
27
+ JOIN app.users u ON u.id = s.user_id
28
+ WHERE s.token_hash = $1
29
+ AND s.expires_at > NOW()
30
+ AND s.revoked_at IS NULL`,
31
+ [tokenHash]
36
32
  );
37
- if (usernameCheck.rows.length > 0) {
38
- throw new Error(`Username "${username}" is already taken. Try a different one.`);
39
- }
40
33
 
41
- // Create new user
42
- const inserted = await pool.query(
43
- 'INSERT INTO users (username, email, login_status) VALUES ($1, $2, true) RETURNING id, username, email',
44
- [username, email]
45
- );
46
- const newUser = inserted.rows[0];
47
- return { userId: newUser.id, username: newUser.username, email: newUser.email, isNew: true };
34
+ if (result.rows.length === 0) return null;
35
+
36
+ const row = result.rows[0];
37
+ return {
38
+ userId: String(row.user_id),
39
+ username: row.username || 'unknown',
40
+ email: row.email || '',
41
+ };
48
42
  } finally {
49
43
  if (ownPool) await pool.end().catch(() => {});
50
44
  }
51
45
  }
52
46
 
53
47
  /**
54
- * Set login_status to false for the given user.
55
- * @param {string} userId UUID
48
+ * Revoke a CLI session token (logout).
49
+ * @param {string} token raw token
56
50
  * @param {object} [opts] optional overrides for testing
57
- * @param {object} [opts.pool] pg Pool instance (skips internal pool creation)
51
+ * @param {object} [opts.pool] pg Pool instance
58
52
  */
59
- async function logoutUser(userId, opts) {
53
+ async function revokeToken(token, opts) {
54
+ if (!token) return;
55
+
60
56
  const ownPool = !(opts && opts.pool);
61
57
  const pool = (opts && opts.pool) || new Pool(dbConfig);
62
58
  try {
63
- await pool.query('UPDATE users SET login_status = false WHERE id = $1', [userId]);
59
+ const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
60
+ await pool.query(
61
+ 'UPDATE app.user_sessions SET revoked_at = NOW() WHERE token_hash = $1',
62
+ [tokenHash]
63
+ );
64
64
  } finally {
65
65
  if (ownPool) await pool.end().catch(() => {});
66
66
  }
67
67
  }
68
68
 
69
- module.exports = { loginOrRegister, logoutUser };
69
+ module.exports = { validateToken, revokeToken };
@@ -260,7 +260,7 @@ module.exports = async function analyzeCommand(target, flags) {
260
260
  // Only show spinner if user is logged in
261
261
  const { loadSession } = require('../../utils/config');
262
262
  const session = loadSession();
263
- if (session.userId) {
263
+ if (session.token) {
264
264
  syncSpinner.start();
265
265
  }
266
266
 
@@ -1,68 +1,117 @@
1
1
  'use strict';
2
2
 
3
- const readline = require('readline');
3
+ const http = require('http');
4
+ const crypto = require('crypto');
4
5
  const pc = require('picocolors');
5
6
  const { saveSession, loadSession } = require('../../utils/config');
6
- const { loginOrRegister } = require('../../api/auth');
7
+
8
+ const WEB_URL = 'https://weci-holic.hackathon.sev-2.com';
7
9
 
8
10
  /**
9
- * Prompt user for input (visible).
11
+ * Open a URL in the default browser (cross-platform).
10
12
  */
11
- function prompt(question) {
12
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
13
- return new Promise((resolve) => {
14
- rl.question(question, (answer) => {
15
- rl.close();
16
- resolve(answer.trim());
17
- });
18
- });
13
+ function openBrowser(url) {
14
+ const { exec } = require('child_process');
15
+ const cmd = process.platform === 'win32' ? `start "" "${url}"`
16
+ : process.platform === 'darwin' ? `open "${url}"`
17
+ : `xdg-open "${url}"`;
18
+ exec(cmd);
19
19
  }
20
20
 
21
+ /**
22
+ * Spawn a temporary local HTTP server, open the browser for GitHub OAuth,
23
+ * and wait for the web app to redirect the token back.
24
+ *
25
+ * Flow:
26
+ * 1. CLI starts local server on a random port
27
+ * 2. CLI opens browser to {WEB_URL}/cli-auth?code={CODE}&port={PORT}
28
+ * 3. User logs in with GitHub on the web app
29
+ * 4. Web app creates a session token and redirects to http://localhost:{PORT}/callback?token=...&username=...&email=...
30
+ * 5. CLI receives the token, saves session, and shuts down local server
31
+ */
21
32
  module.exports = async function loginCommand() {
22
33
  const session = loadSession();
23
- if (session.userId) {
34
+ if (session.token) {
24
35
  console.log(pc.yellow(`Already logged in as ${session.username} (${session.email}).`));
25
36
  console.log(`Run ${pc.cyan('legacyver logout')} first to switch accounts.`);
26
37
  return;
27
38
  }
28
39
 
29
40
  console.log(pc.bold('\nLegacyver Login\n'));
30
- console.log(pc.dim('Your account is used to sync generated docs to the cloud.'));
31
- console.log(pc.dim('If you don\'t have an account, one will be created automatically.\n'));
41
+ console.log(pc.dim('Opening your browser to log in with GitHub...\n'));
32
42
 
33
- const email = await prompt(' Email: ');
34
- if (!email || !email.includes('@')) {
35
- console.error(pc.red('Invalid email address.'));
36
- process.exit(1);
37
- }
43
+ const code = crypto.randomBytes(16).toString('hex');
38
44
 
39
- const username = await prompt(' Username: ');
40
- if (!username || username.length < 2) {
41
- console.error(pc.red('Username must be at least 2 characters.'));
42
- process.exit(1);
43
- }
45
+ return new Promise((resolve, reject) => {
46
+ const server = http.createServer((req, res) => {
47
+ const url = new URL(req.url, `http://localhost`);
48
+
49
+ if (url.pathname === '/callback') {
50
+ const token = url.searchParams.get('token');
51
+ const username = url.searchParams.get('username');
52
+ const email = url.searchParams.get('email');
53
+
54
+ if (token && username) {
55
+ // Save session with the token
56
+ saveSession({
57
+ token,
58
+ username,
59
+ email: email || '',
60
+ });
61
+
62
+ // Send a nice HTML response to the browser
63
+ res.writeHead(200, { 'Content-Type': 'text/html' });
64
+ res.end(`
65
+ <html>
66
+ <body style="background:#0a0a0a;color:#fff;font-family:monospace;display:flex;align-items:center;justify-content:center;height:100vh;margin:0">
67
+ <div style="text-align:center">
68
+ <h1 style="color:#22c55e">Logged in!</h1>
69
+ <p>You can close this tab and return to the CLI.</p>
70
+ </div>
71
+ </body>
72
+ </html>
73
+ `);
44
74
 
45
- try {
46
- const result = await loginOrRegister(email, username);
47
- saveSession({
48
- userId: result.userId,
49
- username: result.username,
50
- email: result.email,
75
+ console.log(pc.green(` Logged in as ${username} (${email})`));
76
+ console.log(pc.dim(' Generated docs will now sync to the cloud after each analyze run.\n'));
77
+
78
+ // Shut down server after a short delay
79
+ setTimeout(() => {
80
+ server.close();
81
+ resolve();
82
+ }, 500);
83
+ } else {
84
+ res.writeHead(400, { 'Content-Type': 'text/plain' });
85
+ res.end('Missing token or username in callback.');
86
+ }
87
+ return;
88
+ }
89
+
90
+ // Any other path
91
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
92
+ res.end('Not found');
51
93
  });
52
94
 
53
- if (result.isNew) {
54
- console.log(pc.green(`\n Account created! Logged in as ${result.username} (${result.email})`));
55
- } else {
56
- console.log(pc.green(`\n Logged in as ${result.username} (${result.email})`));
57
- }
58
- console.log(pc.dim(' Generated docs will now sync to the cloud after each analyze run.\n'));
59
- } catch (err) {
60
- if (err.message.includes('already taken')) {
61
- console.error(pc.red(`\n ${err.message}`));
62
- } else {
63
- console.error(pc.red(`\n Login failed: ${err.message}`));
64
- console.error(pc.dim(' Check your internet connection and try again.'));
65
- }
66
- process.exit(1);
67
- }
95
+ // Listen on a random available port
96
+ server.listen(0, '127.0.0.1', () => {
97
+ const port = server.address().port;
98
+ const authUrl = `${WEB_URL}/cli-auth?code=${code}&port=${port}`;
99
+
100
+ console.log(pc.dim(` Listening on http://localhost:${port}`));
101
+ console.log(pc.dim(` If the browser doesn't open, visit:\n`));
102
+ console.log(` ${pc.cyan(authUrl)}\n`);
103
+ console.log(pc.dim(' Waiting for authentication...\n'));
104
+
105
+ openBrowser(authUrl);
106
+ });
107
+
108
+ // Timeout after 5 minutes
109
+ const timeout = setTimeout(() => {
110
+ console.error(pc.red('\n Login timed out. Please try again.'));
111
+ server.close();
112
+ reject(new Error('Login timed out'));
113
+ }, 5 * 60 * 1000);
114
+
115
+ server.on('close', () => clearTimeout(timeout));
116
+ });
68
117
  };
@@ -2,17 +2,17 @@
2
2
 
3
3
  const pc = require('picocolors');
4
4
  const { loadSession, clearSession } = require('../../utils/config');
5
- const { logoutUser } = require('../../api/auth');
5
+ const { revokeToken } = require('../../api/auth');
6
6
 
7
7
  module.exports = async function logoutCommand() {
8
8
  const session = loadSession();
9
- if (!session.userId) {
9
+ if (!session.token) {
10
10
  console.log('You are not logged in.');
11
11
  return;
12
12
  }
13
13
 
14
14
  try {
15
- await logoutUser(session.userId);
15
+ await revokeToken(session.token);
16
16
  } catch {
17
17
  // DB update failed — still clear local session
18
18
  }
@@ -20,7 +20,7 @@ module.exports = async function providersCommand() {
20
20
  // ─── Legacyver Account ────────────────────────────────────────────────────
21
21
  const session = loadSession();
22
22
  console.log(pc.bold('\nLegacyver Account'));
23
- if (session.userId) {
23
+ if (session.token) {
24
24
  console.log(` ${pc.green('Logged in')} as ${session.username} (${session.email})`);
25
25
  console.log(' Generated docs will sync to the cloud after each analyze run.');
26
26
  } else {
package/src/cli/ui.js CHANGED
@@ -84,7 +84,7 @@ function printSummary(stats) {
84
84
  // Show login tip if user is not logged in
85
85
  const { loadSession } = require('../utils/config');
86
86
  const session = loadSession();
87
- if (!session.userId) {
87
+ if (!session.token) {
88
88
  console.log(pc.dim('─────────────────────────────────────────────────'));
89
89
  console.log(pc.cyan(' Sync docs to the cloud:'));
90
90
  console.log('');
package/src/db/index.js CHANGED
@@ -4,6 +4,7 @@ const { Pool } = require('pg');
4
4
  const path = require('path');
5
5
  const dbConfig = require('./config');
6
6
  const { loadSession } = require('../utils/config');
7
+ const { validateToken } = require('../api/auth');
7
8
  const logger = require('../utils/logger');
8
9
 
9
10
  let _pool = null;
@@ -21,7 +22,7 @@ function getPool() {
21
22
  /**
22
23
  * Find or create a repository for the given user + project path.
23
24
  * @param {Pool} pool
24
- * @param {string} userId UUID
25
+ * @param {string} userId app.users.id (BIGINT as string)
25
26
  * @param {string} projectPath absolute path of the analyzed directory
26
27
  * @returns {Promise<string>} repository id (UUID)
27
28
  */
@@ -31,7 +32,7 @@ async function getOrCreateRepo(pool, userId, projectPath) {
31
32
 
32
33
  // Try find existing
33
34
  const existing = await pool.query(
34
- 'SELECT id FROM repositories WHERE user_id = $1 AND full_name = $2',
35
+ 'SELECT id FROM app.repositories WHERE user_id = $1 AND full_name = $2',
35
36
  [userId, fullName]
36
37
  );
37
38
  if (existing.rows.length > 0) {
@@ -40,7 +41,7 @@ async function getOrCreateRepo(pool, userId, projectPath) {
40
41
 
41
42
  // Insert new
42
43
  const inserted = await pool.query(
43
- 'INSERT INTO repositories (user_id, name, full_name) VALUES ($1, $2, $3) RETURNING id',
44
+ 'INSERT INTO app.repositories (user_id, name, full_name) VALUES ($1, $2, $3) RETURNING id',
44
45
  [userId, name, fullName]
45
46
  );
46
47
  return inserted.rows[0].id;
@@ -56,7 +57,7 @@ async function getOrCreateRepo(pool, userId, projectPath) {
56
57
  */
57
58
  async function getOrCreateDocumentation(pool, repositoryId, repoName) {
58
59
  const existing = await pool.query(
59
- 'SELECT id FROM documentations WHERE repository_id = $1',
60
+ 'SELECT id FROM app.documentations WHERE repository_id = $1',
60
61
  [repositoryId]
61
62
  );
62
63
  if (existing.rows.length > 0) {
@@ -64,7 +65,7 @@ async function getOrCreateDocumentation(pool, repositoryId, repoName) {
64
65
  }
65
66
 
66
67
  const inserted = await pool.query(
67
- 'INSERT INTO documentations (repository_id, title, description) VALUES ($1, $2, $3) RETURNING id',
68
+ 'INSERT INTO app.documentations (repository_id, title, description) VALUES ($1, $2, $3) RETURNING id',
68
69
  [repositoryId, `${repoName} Documentation`, `Auto-generated documentation for ${repoName}`]
69
70
  );
70
71
  return inserted.rows[0].id;
@@ -88,20 +89,20 @@ async function upsertPages(pool, documentationId, fragments) {
88
89
 
89
90
  // Check if page exists
90
91
  const existing = await pool.query(
91
- 'SELECT id FROM documentation_pages WHERE documentation_id = $1 AND slug = $2',
92
+ 'SELECT id FROM app.documentation_pages WHERE documentation_id = $1 AND slug = $2',
92
93
  [documentationId, slug]
93
94
  );
94
95
 
95
96
  if (existing.rows.length > 0) {
96
97
  // Update existing
97
98
  await pool.query(
98
- 'UPDATE documentation_pages SET content = $1, title = $2, page_order = $3, created_at = NOW() WHERE id = $4',
99
+ 'UPDATE app.documentation_pages SET content = $1, title = $2, page_order = $3, created_at = NOW() WHERE id = $4',
99
100
  [frag.content, title, i + 1, existing.rows[0].id]
100
101
  );
101
102
  } else {
102
103
  // Insert new
103
104
  await pool.query(
104
- 'INSERT INTO documentation_pages (documentation_id, slug, title, content, page_order) VALUES ($1, $2, $3, $4, $5)',
105
+ 'INSERT INTO app.documentation_pages (documentation_id, slug, title, content, page_order) VALUES ($1, $2, $3, $4, $5)',
105
106
  [documentationId, slug, title, frag.content, i + 1]
106
107
  );
107
108
  }
@@ -112,25 +113,36 @@ async function upsertPages(pool, documentationId, fragments) {
112
113
 
113
114
  /**
114
115
  * Top-level push function. Called from analyze command.
115
- * Short-circuits if user is not logged in.
116
+ * Validates the CLI token, then pushes docs to DB.
117
+ * Short-circuits if user is not logged in or token is invalid.
116
118
  * @param {Array<{relativePath: string, content: string}>} fragments
117
119
  * @param {string} projectPath absolute path of the analyzed directory
118
120
  * @param {object} [opts] optional overrides for testing
119
121
  * @param {object} [opts.pool] pg Pool instance (skips singleton pool)
120
122
  * @param {object} [opts.session] session object (skips loadSession)
123
+ * @param {object} [opts.user] user object (skips validateToken) — { userId, username, email }
121
124
  * @returns {Promise<{skipped: boolean, pushed?: number}>}
122
125
  */
123
126
  async function pushToDatabase(fragments, projectPath, opts) {
124
127
  const session = (opts && opts.session) || loadSession();
125
- if (!session.userId) {
128
+ if (!session.token) {
126
129
  return { skipped: true };
127
130
  }
128
131
 
132
+ // Validate the token to get user info
133
+ let user = (opts && opts.user) || null;
134
+ if (!user) {
135
+ user = await validateToken(session.token);
136
+ if (!user) {
137
+ return { skipped: true };
138
+ }
139
+ }
140
+
129
141
  const ownPool = !(opts && opts.pool);
130
142
  const pool = (opts && opts.pool) || getPool();
131
143
  try {
132
144
  const repoName = path.basename(projectPath);
133
- const repoId = await getOrCreateRepo(pool, session.userId, projectPath);
145
+ const repoId = await getOrCreateRepo(pool, user.userId, projectPath);
134
146
  const docId = await getOrCreateDocumentation(pool, repoId, repoName);
135
147
  const pushed = await upsertPages(pool, docId, fragments);
136
148
  return { skipped: false, pushed };
package/.env DELETED
@@ -1 +0,0 @@
1
- GROQ_API_KEY = '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'
package/.env.example DELETED
@@ -1,17 +0,0 @@
1
- # Legacyver Environment Variables
2
- # Copy this file to .env and fill in your API keys
3
-
4
- # Groq API Key (required for groq provider - free tier available at https://console.groq.com)
5
- GROQ_API_KEY=your_groq_api_key_here
6
-
7
- # Ollama API URL (optional, defaults to http://localhost:11434)
8
- # OLLAMA_BASE_URL=http://localhost:11434
9
-
10
- # OpenRouter API Key (optional, for openrouter provider)
11
- # OPENROUTER_API_KEY=your_openrouter_key_here
12
-
13
- # Gemini API Key (optional, for gemini provider)
14
- # GEMINI_API_KEY=your_gemini_key_here
15
-
16
- # Kimi API Key (optional, for kimi provider)
17
- # KIMI_API_KEY=your_kimi_key_here
@@ -1,61 +0,0 @@
1
- # Team Infrastructure Usage Guide
2
-
3
- Welcome to your team infrastructure folder! Here’s how to use the files provided:
4
-
5
- ## 1. `domain.txt`
6
-
7
- - This file contains your public application domain in the format:
8
-
9
- `https://<team-name>.hackathon.sev-2.com`
10
-
11
- - This domain will be configured in the Kubernetes ingress, so your deployed app will be accessible at this address.
12
-
13
-
14
- ## 2. `db-credentials.txt`
15
-
16
- - This file contains your team's PostgreSQL database username, password, and database name.
17
- - You can find it in your team folder: `db-credentials.txt`.
18
- - Example content:
19
-
20
- ```
21
- rdms = "PostgreSQL"
22
- host = "localhost"
23
- port = 5432
24
- username = "your_team_user"
25
- password = "your_team_password"
26
- database = "your_team_db"
27
- ```
28
-
29
- - Use these credentials to connect your app or a database client to your team's schema.
30
-
31
- ## 3. `kubeconfig.yaml`
32
-
33
- - This file allows you to connect to your team’s Kubernetes namespace/cluster.
34
- - Usage example:
35
-
36
- ```sh
37
- kubectl --kubeconfig=./kubeconfig.yaml -n <team-name> get pods
38
- ```
39
-
40
- - You can use this file with `kubectl` or any Kubernetes-compatible tool.
41
-
42
- ## Deployment Steps
43
-
44
- 1. Dockerize your app
45
- 2. Push your image to your container registry (e.g., Docker Hub).
46
- 3. Deploy your application as usual (e.g., with `kubectl apply -f ...`).
47
- 4. Ensure your app’s ingress resource uses the domain from `domain.txt`.
48
- 5. Access your app at the public URL after deployment.
49
-
50
- ---
51
-
52
- If you have questions, contact the hackathon team.
53
-
54
- ---
55
-
56
-
57
- ## Useful Links
58
-
59
- - [Kubernetes for Beginners (FreeCodeCamp)](https://www.freecodecamp.org/news/the-kubernetes-handbook/)
60
- - [kubectl Cheat Sheet (Kubernetes Official)](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)
61
- - [Kubernetes Ingress Guide (Solo.io)](https://www.solo.io/topics/api-gateway/kubernetes-ingress)
@@ -1,6 +0,0 @@
1
- rdms = "PostgreSQL"
2
- host = "103.185.52.138"
3
- port = 1185
4
- username = "weci_holic"
5
- database = "weci_holic"
6
- password = "f==+HLH_bvzLN2fo82f3x239MZE3@bGF"
@@ -1 +0,0 @@
1
- https://weci-holic.hackathon.sev-2.com
@@ -1,18 +0,0 @@
1
- apiVersion: v1
2
- kind: Config
3
- clusters:
4
- - name: local
5
- cluster:
6
- server: "https://103.185.52.45:6443"
7
- certificate-authority-data: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTnpFek9UQTRNRFF3SGhjTk1qWXdNakU0TURVd01EQTBXaGNOTXpZd01qRTJNRFV3TURBMApXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTnpFek9UQTRNRFF3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTckpZTUNCdG9kU2lGZ2k1bkJ0YnNRaE4wcTRnSmRJQ2lzeGRwN2FGR00KcTVaWk5iQXpLbjNrd05hU2JmZ2sxL2xUQWFIWnFSUlI0czdqaEFIclhUMjZvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXdHdVk4YVZ2QzVURDZnaUdFQlNTCmRrK2loU2t3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnYld1Y1NkQUVsZ3orcmp2Z1hrU0hXTTRSQnlrQVo4VjQKWDBlTjhYZzdJMmNDSVFDZWRtR2pVMzVQaUtheVFnQS9NWHJMd2ZyL1pBeUU3eUJzWHo2bGN5VFZKZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
8
- contexts:
9
- - name: weci-holic
10
- context:
11
- cluster: local
12
- namespace: weci-holic
13
- user: weci-holic-sa
14
- current-context: weci-holic
15
- users:
16
- - name: weci-holic-sa
17
- user:
18
- token: eyJhbGciOiJSUzI1NiIsImtpZCI6IlFteFl2cGk1RkF5TEFkdDJYSC05UnVmUGJhYXJCU0pBNjNEcUZxcEtsdFUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJ3ZWNpLWhvbGljIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6IndlY2ktaG9saWMtc2EtdG9rZW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoid2VjaS1ob2xpYy1zYSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjhlNjY0ZmQyLWNkNTYtNGEyNi1iNjE5LWRjYzg1Y2Y2ZWFjMiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDp3ZWNpLWhvbGljOndlY2ktaG9saWMtc2EifQ.jlBrE-ajb4CCj2244Kl-B-5jXikmNOh1kwbnMKttZFE8OJSi9xUEc1x6oQni1P83p5pkbqvreZpN8FtA-_YiMJpyMkjInWogfBc7TVvymJ0F0KQ-Ybxu2ibxkQvOOlNLuctCq4NbCm0oQaH3iBlvsFMpKuZJnogDwEbc6fompYrsxdXGh4F-zoh91mGiSsc7vyLfNJrKQvkivoOoaVwP2Y9xIZUnXMiTCExLUo1DthbRVN4PMPiCytJ6Tvg4LSMruu9-nW2be1hCgTV5IffB4hlhIgaWwCpBzygiWM4--Yg0tS-lejbquehDhVTWMkeOoZqzRKnMdU5iVyxBGB0pOA
@@ -1,2 +0,0 @@
1
- Kubernetes Namespace: weci-holic
2
- Kubernetes Config: kubeconfig.yaml