@vibe-assurance/cli 1.7.9 → 1.10.0

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": "@vibe-assurance/cli",
3
- "version": "1.7.9",
3
+ "version": "1.10.0",
4
4
  "description": "Vibe Assurance CLI - Connect AI coding agents to your governance platform via MCP",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/api/client.js CHANGED
@@ -29,7 +29,7 @@ const API_BASE_URL = process.env.VIBE_API_URL || getEnvironmentUrl(DEFAULT_ENVIR
29
29
  * @returns {Promise<import('axios').AxiosInstance>}
30
30
  */
31
31
  async function createClient() {
32
- const creds = await getCredentials();
32
+ let creds = await getCredentials();
33
33
  if (!creds || !creds.accessToken) {
34
34
  throw new Error('Not authenticated. Run: vibe login');
35
35
  }
@@ -37,13 +37,37 @@ async function createClient() {
37
37
  // CR-2026-061: Get API URL from stored environment
38
38
  const apiBaseUrl = await getApiBaseUrl();
39
39
 
40
+ // Pre-emptive token refresh: If token expires within 5 minutes, refresh now
41
+ // This avoids race conditions where the token expires during an API call
42
+ if (creds.expiresAt && creds.refreshToken) {
43
+ const expiresAt = new Date(creds.expiresAt);
44
+ const now = new Date();
45
+ const bufferMs = 5 * 60 * 1000; // 5 minutes
46
+
47
+ if (expiresAt.getTime() - bufferMs < now.getTime()) {
48
+ try {
49
+ const newTokens = await refreshToken(creds.refreshToken);
50
+ // Preserve existing credentials (environment, projectId, user info)
51
+ creds = {
52
+ ...creds,
53
+ ...newTokens
54
+ };
55
+ await storeCredentials(creds);
56
+ } catch (refreshError) {
57
+ // Pre-emptive refresh failed - will try again on 401
58
+ // Don't throw here, let the request proceed with old token
59
+ console.error('Pre-emptive token refresh failed, will retry on 401');
60
+ }
61
+ }
62
+ }
63
+
40
64
  // CR-2026-043: Get current project ID for scoping
41
65
  const projectId = await getProjectId();
42
66
 
43
67
  const headers = {
44
68
  'Authorization': `Bearer ${creds.accessToken}`,
45
69
  'Content-Type': 'application/json',
46
- 'User-Agent': 'vibe-cli/1.7.0'
70
+ 'User-Agent': 'vibe-cli/1.10.0'
47
71
  };
48
72
 
49
73
  // CR-2026-043: Add project header if available
@@ -69,7 +93,14 @@ async function createClient() {
69
93
 
70
94
  try {
71
95
  const newTokens = await refreshToken(creds.refreshToken);
72
- await storeCredentials(newTokens);
96
+
97
+ // CRITICAL: Preserve existing credentials (environment, projectId, user info)
98
+ // when storing new tokens. Only update token-related fields.
99
+ const currentCreds = await getCredentials();
100
+ await storeCredentials({
101
+ ...currentCreds, // Preserve environment, projectId, username, email, role, etc.
102
+ ...newTokens // Update accessToken, refreshToken, expiresAt
103
+ });
73
104
 
74
105
  // Update the failed request with new token
75
106
  originalRequest.headers['Authorization'] = `Bearer ${newTokens.accessToken}`;
package/src/mcp/tools.js CHANGED
@@ -223,7 +223,7 @@ const tools = [
223
223
  properties: {
224
224
  type: {
225
225
  type: 'string',
226
- enum: ['CR', 'RISK', 'VULNERABILITY', 'REPORT', 'POLICY', 'PLAN', 'ARCHITECTURE', 'CONFIG', 'SOP'],
226
+ enum: ['CR', 'RISK', 'VULNERABILITY', 'REPORT', 'STANDARD', 'PLAN', 'ARCHITECTURE', 'CONFIG'],
227
227
  description: 'Type of artifact'
228
228
  },
229
229
  artifactId: {
@@ -348,7 +348,7 @@ const tools = [
348
348
  properties: {
349
349
  type: {
350
350
  type: 'string',
351
- enum: ['CR', 'RISK', 'VULNERABILITY', 'REPORT', 'POLICY', 'PLAN', 'ARCHITECTURE', 'CONFIG', 'SOP'],
351
+ enum: ['CR', 'RISK', 'VULNERABILITY', 'REPORT', 'STANDARD', 'PLAN', 'ARCHITECTURE', 'CONFIG'],
352
352
  description: 'Filter by artifact type. Use "PLAN" to find strategic plans.'
353
353
  },
354
354
  status: {
@@ -755,6 +755,10 @@ const tools = [
755
755
  location: {
756
756
  type: 'string',
757
757
  description: 'File path or component where vulnerability exists'
758
+ },
759
+ remediationPlanId: {
760
+ type: 'string',
761
+ description: 'Link to remediation plan (e.g., "RMP-VUL-001")'
758
762
  }
759
763
  },
760
764
  required: ['vulId', 'title', 'description', 'severity']
@@ -784,7 +788,7 @@ const tools = [
784
788
 
785
789
  {
786
790
  name: 'vibe_update_vulnerability',
787
- description: 'Update a vulnerability\'s status, severity, or link it to a remediation CR.',
791
+ description: 'Update a vulnerability\'s status, severity, link it to a remediation CR, or link to a remediation plan.',
788
792
  inputSchema: {
789
793
  type: 'object',
790
794
  properties: {
@@ -805,6 +809,10 @@ const tools = [
805
809
  relatedCR: {
806
810
  type: 'string',
807
811
  description: 'Link to remediation CR (e.g., "CR-2026-042")'
812
+ },
813
+ remediationPlanId: {
814
+ type: 'string',
815
+ description: 'Link to remediation plan (e.g., "RMP-VUL-001")'
808
816
  }
809
817
  },
810
818
  required: ['vulId']
@@ -815,139 +823,19 @@ const tools = [
815
823
  },
816
824
 
817
825
  // ============================================================================
818
- // SOP MANAGEMENT TOOLS (CR-2026-054)
819
- // ============================================================================
820
-
821
- {
822
- name: 'vibe_list_sops',
823
- description: 'List all Standard Operating Procedures (SOPs) for the project. SOPs define step-by-step procedures for operational tasks.',
824
- inputSchema: {
825
- type: 'object',
826
- properties: {
827
- status: {
828
- type: 'string',
829
- enum: ['Draft', 'Active', 'Completed', 'Closed'],
830
- description: 'Filter by SOP status'
831
- },
832
- category: {
833
- type: 'string',
834
- description: 'Filter by category (e.g., "Security", "HR", "SDLC", "Change Management")'
835
- }
836
- }
837
- },
838
- handler: async (params = {}) => {
839
- const query = new URLSearchParams();
840
- if (params.status) query.set('status', params.status);
841
- if (params.category) query.set('category', params.category);
842
- const queryString = query.toString();
843
- const path = queryString ? `/api/mcp/sops?${queryString}` : '/api/mcp/sops';
844
- return await api.get(path);
845
- }
846
- },
847
-
848
- {
849
- name: 'vibe_store_sop',
850
- description: 'Create a new Standard Operating Procedure (SOP). SOPs define step-by-step procedures for operational tasks like onboarding, offboarding, access reviews, etc.',
851
- inputSchema: {
852
- type: 'object',
853
- properties: {
854
- sopId: {
855
- type: 'string',
856
- description: 'Unique SOP ID (e.g., "SOP-001", "SOP-SDLC-001")'
857
- },
858
- title: {
859
- type: 'string',
860
- description: 'Title of the SOP (e.g., "Employee Onboarding Checklist")'
861
- },
862
- content: {
863
- type: 'string',
864
- description: 'Full SOP content in markdown format'
865
- },
866
- status: {
867
- type: 'string',
868
- enum: ['Draft', 'Active', 'Completed', 'Closed'],
869
- description: 'SOP status (default: Active)'
870
- },
871
- metadata: {
872
- type: 'object',
873
- description: 'Additional metadata (e.g., category, version, owner)',
874
- additionalProperties: true
875
- }
876
- },
877
- required: ['sopId', 'title', 'content']
878
- },
879
- handler: async (params) => {
880
- return await api.post('/api/mcp/sops', params);
881
- }
882
- },
883
-
884
- {
885
- name: 'vibe_get_sop',
886
- description: 'Get a specific SOP by ID with full content.',
887
- inputSchema: {
888
- type: 'object',
889
- properties: {
890
- sopId: {
891
- type: 'string',
892
- description: 'The SOP ID to retrieve (e.g., "SOP-001")'
893
- }
894
- },
895
- required: ['sopId']
896
- },
897
- handler: async ({ sopId }) => {
898
- return await api.get(`/api/mcp/sops/${sopId}`);
899
- }
900
- },
901
-
902
- {
903
- name: 'vibe_update_sop',
904
- description: 'Update an existing SOP\'s content, status, or metadata.',
905
- inputSchema: {
906
- type: 'object',
907
- properties: {
908
- sopId: {
909
- type: 'string',
910
- description: 'The SOP ID to update'
911
- },
912
- title: {
913
- type: 'string',
914
- description: 'Updated title'
915
- },
916
- content: {
917
- type: 'string',
918
- description: 'Updated content'
919
- },
920
- status: {
921
- type: 'string',
922
- enum: ['Draft', 'Active', 'Completed', 'Closed'],
923
- description: 'Updated status'
924
- },
925
- metadata: {
926
- type: 'object',
927
- description: 'Updated metadata'
928
- }
929
- },
930
- required: ['sopId']
931
- },
932
- handler: async ({ sopId, ...updates }) => {
933
- return await api.put(`/api/mcp/sops/${sopId}`, updates);
934
- }
935
- },
936
-
937
- // ============================================================================
938
- // POLICY MANAGEMENT TOOLS (CR-2026-054)
826
+ // STANDARDS MANAGEMENT TOOLS (CR-2026-063: Renamed from Policies)
939
827
  // ============================================================================
940
828
 
941
829
  {
942
- name: 'vibe_list_policies',
943
- description: 'List all policies for the project. Policies define organizational rules and guidelines.',
830
+ name: 'vibe_list_standards',
831
+ description: 'List all standards for the project. Standards define organizational coding standards, security guidelines, and best practices.',
944
832
  inputSchema: {
945
833
  type: 'object',
946
834
  properties: {
947
835
  status: {
948
836
  type: 'string',
949
837
  enum: ['Draft', 'Active', 'Completed', 'Closed'],
950
- description: 'Filter by policy status'
838
+ description: 'Filter by standard status'
951
839
  },
952
840
  category: {
953
841
  type: 'string',
@@ -960,33 +848,33 @@ const tools = [
960
848
  if (params.status) query.set('status', params.status);
961
849
  if (params.category) query.set('category', params.category);
962
850
  const queryString = query.toString();
963
- const path = queryString ? `/api/mcp/policies?${queryString}` : '/api/mcp/policies';
851
+ const path = queryString ? `/api/mcp/standards?${queryString}` : '/api/mcp/standards';
964
852
  return await api.get(path);
965
853
  }
966
854
  },
967
855
 
968
856
  {
969
- name: 'vibe_store_policy',
970
- description: 'Create a new policy document. Policies define organizational rules and guidelines for security, HR, SDLC, etc.',
857
+ name: 'vibe_store_standard',
858
+ description: 'Create a new standard document. Standards define organizational coding standards, security guidelines, and best practices.',
971
859
  inputSchema: {
972
860
  type: 'object',
973
861
  properties: {
974
- policyId: {
862
+ standardId: {
975
863
  type: 'string',
976
- description: 'Unique policy ID (e.g., "POL-001", "POL-SEC-001")'
864
+ description: 'Unique standard ID (e.g., "STD-001", "STD-SEC-001")'
977
865
  },
978
866
  title: {
979
867
  type: 'string',
980
- description: 'Title of the policy (e.g., "Information Security Policy")'
868
+ description: 'Title of the standard (e.g., "Secure Coding Standard")'
981
869
  },
982
870
  content: {
983
871
  type: 'string',
984
- description: 'Full policy content in markdown format'
872
+ description: 'Full standard content in markdown format'
985
873
  },
986
874
  status: {
987
875
  type: 'string',
988
876
  enum: ['Draft', 'Active', 'Completed', 'Closed'],
989
- description: 'Policy status (default: Active)'
877
+ description: 'Standard status (default: Active)'
990
878
  },
991
879
  metadata: {
992
880
  type: 'object',
@@ -994,40 +882,40 @@ const tools = [
994
882
  additionalProperties: true
995
883
  }
996
884
  },
997
- required: ['policyId', 'title', 'content']
885
+ required: ['standardId', 'title', 'content']
998
886
  },
999
887
  handler: async (params) => {
1000
- return await api.post('/api/mcp/policies', params);
888
+ return await api.post('/api/mcp/standards', params);
1001
889
  }
1002
890
  },
1003
891
 
1004
892
  {
1005
- name: 'vibe_get_policy',
1006
- description: 'Get a specific policy by ID with full content.',
893
+ name: 'vibe_get_standard',
894
+ description: 'Get a specific standard by ID with full content.',
1007
895
  inputSchema: {
1008
896
  type: 'object',
1009
897
  properties: {
1010
- policyId: {
898
+ standardId: {
1011
899
  type: 'string',
1012
- description: 'The policy ID to retrieve (e.g., "POL-001")'
900
+ description: 'The standard ID to retrieve (e.g., "STD-001")'
1013
901
  }
1014
902
  },
1015
- required: ['policyId']
903
+ required: ['standardId']
1016
904
  },
1017
- handler: async ({ policyId }) => {
1018
- return await api.get(`/api/mcp/policies/${policyId}`);
905
+ handler: async ({ standardId }) => {
906
+ return await api.get(`/api/mcp/standards/${standardId}`);
1019
907
  }
1020
908
  },
1021
909
 
1022
910
  {
1023
- name: 'vibe_update_policy',
1024
- description: 'Update an existing policy\'s content, status, or metadata.',
911
+ name: 'vibe_update_standard',
912
+ description: 'Update an existing standard\'s content, status, or metadata.',
1025
913
  inputSchema: {
1026
914
  type: 'object',
1027
915
  properties: {
1028
- policyId: {
916
+ standardId: {
1029
917
  type: 'string',
1030
- description: 'The policy ID to update'
918
+ description: 'The standard ID to update'
1031
919
  },
1032
920
  title: {
1033
921
  type: 'string',
@@ -1047,10 +935,10 @@ const tools = [
1047
935
  description: 'Updated metadata'
1048
936
  }
1049
937
  },
1050
- required: ['policyId']
938
+ required: ['standardId']
1051
939
  },
1052
- handler: async ({ policyId, ...updates }) => {
1053
- return await api.put(`/api/mcp/policies/${policyId}`, updates);
940
+ handler: async ({ standardId, ...updates }) => {
941
+ return await api.put(`/api/mcp/standards/${standardId}`, updates);
1054
942
  }
1055
943
  }
1056
944
  ];