From 97b34b4d9e094f10f3046450c7dd8293507a325a Mon Sep 17 00:00:00 2001 From: david-rocca Date: Thu, 7 May 2026 11:12:45 -0400 Subject: [PATCH 1/7] changing contact info object --- api-docs/openapi.json | 2 +- schemas/registry-org/BaseOrg.json | 27 +++++---- schemas/registry-org/CNAOrg.json | 25 +++++--- schemas/registry-org/RootOrg.json | 60 ++++++++++++++----- .../create-registry-org-request.json | 35 +++++------ .../create-registry-org-response.json | 35 +++++------ .../get-registry-org-response.json | 34 ++++++----- .../list-registry-orgs-response.json | 34 ++++++----- .../update-registry-org-request.json | 32 ++++++---- .../update-registry-org-response.json | 35 +++++------ .../audit.controller/audit.controller.js | 3 +- src/controller/glossary.controller/index.js | 22 ++----- src/controller/org.controller/index.js | 7 +-- .../org.controller/org.middleware.js | 23 ++++--- .../registry-org.middleware.js | 2 +- src/middleware/schemas/BaseOrg.json | 30 +++++----- src/model/baseorg.js | 7 +-- src/repositories/baseOrgRepository.js | 8 +-- src/scripts/migrate.js | 17 ++---- test/integration-tests/constants.js | 21 +++---- test/integration-tests/org/postOrgTest.js | 2 +- .../registryOrgWithJointReviewTest.js | 12 ++-- .../registry-org/verifyDeepRemoveEmpty.js | 12 ++-- .../review-object/reviewObjectTest.js | 6 +- 24 files changed, 260 insertions(+), 231 deletions(-) diff --git a/api-docs/openapi.json b/api-docs/openapi.json index 6a5872063..83e6177e0 100644 --- a/api-docs/openapi.json +++ b/api-docs/openapi.json @@ -2605,7 +2605,7 @@ "Registry Organization" ], "summary": "Updates information about the organization specified by short name (accessible Temporarily to Secretariat only)", - "description": "

Access Control

User must belong to an organization with the Secretariat role temporarily.

In the future, only the organization's admin will be able to request changes to its information.

With Joint Approval required for the following fields:

Expected Behavior

This endpoint expects a full organization object in the request body.

Secretariat: Updates any organization's information

Organization Admin: Requests changes to its organization's information

", + "description": "

Access Control

User must belong to an organization with the Secretariat role temporarily.

In the future, only the organization's admin will be able to request changes to its information.

With Joint Approval required for the following fields:

Expected Behavior

This endpoint expects a full organization object in the request body.

Secretariat: Updates any organization's information

Organization Admin: Requests changes to its organization's information

", "operationId": "orgUpdateSingle", "parameters": [ { diff --git a/schemas/registry-org/BaseOrg.json b/schemas/registry-org/BaseOrg.json index d47c19729..f1e8ef02f 100644 --- a/schemas/registry-org/BaseOrg.json +++ b/schemas/registry-org/BaseOrg.json @@ -140,19 +140,24 @@ "contact_info": { "type": "object", "properties": { - "phone": { - "type": "string" - }, - "poc": { - "type": "string" + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true }, - "poc_email": { - "type": "string", - "format": "email" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true }, - "website": { - "type": "string", - "format": "uri" + "phone": { + "type": "string" } }, "additionalProperties": false diff --git a/schemas/registry-org/CNAOrg.json b/schemas/registry-org/CNAOrg.json index 0b86c1a9a..bdcfedc85 100644 --- a/schemas/registry-org/CNAOrg.json +++ b/schemas/registry-org/CNAOrg.json @@ -45,16 +45,23 @@ "contact_info": { "type": "object", "properties": { - "phone": { - "type": "string" - }, - "poc": { - "type": "string" + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true }, - "poc_email": { - "type": "string" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true }, - "website": { + "phone": { "type": "string" } }, @@ -136,4 +143,4 @@ "short_name", "hard_quota" ] -} \ No newline at end of file +} diff --git a/schemas/registry-org/RootOrg.json b/schemas/registry-org/RootOrg.json index d4c090444..aef1f5494 100644 --- a/schemas/registry-org/RootOrg.json +++ b/schemas/registry-org/RootOrg.json @@ -6,16 +6,24 @@ "description": "Schema for a CVE Root Organization", "additionalProperties": false, "properties": { - "UUID": { "$ref": "/BaseOrg#/definitions/uuidType" }, - "short_name": { "$ref": "/BaseOrg#/definitions/shortName" }, - "long_name": { "$ref": "/BaseOrg#/definitions/longName" }, + "UUID": { + "$ref": "/BaseOrg#/definitions/uuidType" + }, + "short_name": { + "$ref": "/BaseOrg#/definitions/shortName" + }, + "long_name": { + "$ref": "/BaseOrg#/definitions/longName" + }, "new_short_name": { "description": "Used to rename an organization's short name during an update.", "type": "string", "minLength": 2, "maxLength": 32 }, - "aliases": { "$ref": "/BaseOrg#/properties/aliases" }, + "aliases": { + "$ref": "/BaseOrg#/properties/aliases" + }, "private_contacts": { "type": "array", "items": { @@ -37,11 +45,25 @@ "contact_info": { "type": "object", "properties": { - "poc": { "type": "string" }, - "poc_email": { "type": "string" }, - "poc_phone": { "type": "string" }, - "org_email": { "type": "string" }, - "website": { "type": "string" } + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true + }, + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true + }, + "phone": { + "type": "string" + } }, "additionalProperties": false }, @@ -68,10 +90,20 @@ "partner_country": { "type": "string" }, - "advisory_locations": { "$ref": "/BaseOrg#/properties/advisory_locations" }, - "program_data": { "$ref": "/BaseOrg#/properties/program_data" }, - "industry": { "$ref": "/BaseOrg#/properties/industry" }, - "top_level_root": { "$ref": "/BaseOrg#/properties/top_level_root" } + "advisory_locations": { + "$ref": "/BaseOrg#/properties/advisory_locations" + }, + "program_data": { + "$ref": "/BaseOrg#/properties/program_data" + }, + "industry": { + "$ref": "/BaseOrg#/properties/industry" + }, + "top_level_root": { + "$ref": "/BaseOrg#/properties/top_level_root" + } }, - "required": ["short_name"] + "required": [ + "short_name" + ] } diff --git a/schemas/registry-org/create-registry-org-request.json b/schemas/registry-org/create-registry-org-request.json index 718778634..cfa8b9f09 100644 --- a/schemas/registry-org/create-registry-org-request.json +++ b/schemas/registry-org/create-registry-org-request.json @@ -85,26 +85,27 @@ "contact_info": { "type": "object", "properties": { - "phone": { - "type": "string" - }, - "poc": { - "type": "string" + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true }, - "poc_email": { - "type": "string", - "format": "email" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true }, - "website": { - "type": "string", - "format": "uri" + "phone": { + "type": "string" } }, - "required": [ - "poc", - "poc_email", - "admins" - ] + "additionalProperties": false }, "advisory_locations": { "type": "array", @@ -190,4 +191,4 @@ "authority", "long_name" ] -} \ No newline at end of file +} diff --git a/schemas/registry-org/create-registry-org-response.json b/schemas/registry-org/create-registry-org-response.json index 9c8cb073e..a8ef091f1 100644 --- a/schemas/registry-org/create-registry-org-response.json +++ b/schemas/registry-org/create-registry-org-response.json @@ -126,26 +126,27 @@ "contact_info": { "type": "object", "properties": { - "phone": { - "type": "string" - }, - "poc": { - "type": "string" + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true }, - "poc_email": { - "type": "string", - "format": "email" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true }, - "website": { - "type": "string", - "format": "uri" + "phone": { + "type": "string" } }, - "required": [ - "poc", - "poc_email", - "admins" - ] + "additionalProperties": false }, "advisory_locations": { "type": "array", @@ -184,4 +185,4 @@ } } } -} \ No newline at end of file +} diff --git a/schemas/registry-org/get-registry-org-response.json b/schemas/registry-org/get-registry-org-response.json index 121ec7899..a847dc290 100644 --- a/schemas/registry-org/get-registry-org-response.json +++ b/schemas/registry-org/get-registry-org-response.json @@ -91,25 +91,27 @@ "contact_info": { "type": "object", "properties": { - "phone": { - "type": "string" - }, - "poc": { - "type": "string" + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true }, - "poc_email": { - "type": "string", - "format": "email" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true }, - "website": { - "type": "string", - "format": "uri" + "phone": { + "type": "string" } }, - "required": [ - "poc", - "poc_email" - ] + "additionalProperties": false }, "partner_role_type": { "$ref": "/BaseOrg#/definitions/partnerRoleType" @@ -224,4 +226,4 @@ "description": "List of conversation messages associated with the organization" } } -} \ No newline at end of file +} diff --git a/schemas/registry-org/list-registry-orgs-response.json b/schemas/registry-org/list-registry-orgs-response.json index fa6d832de..78b9f215c 100644 --- a/schemas/registry-org/list-registry-orgs-response.json +++ b/schemas/registry-org/list-registry-orgs-response.json @@ -120,25 +120,27 @@ "contact_info": { "type": "object", "properties": { - "phone": { - "type": "string" - }, - "poc": { - "type": "string" + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true }, - "poc_email": { - "type": "string", - "format": "email" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true }, - "website": { - "type": "string", - "format": "uri" + "phone": { + "type": "string" } }, - "required": [ - "poc", - "poc_email" - ] + "additionalProperties": false }, "partner_role_type": { "$ref": "/BaseOrg#/definitions/partnerRoleType" @@ -256,4 +258,4 @@ } } } -} \ No newline at end of file +} diff --git a/schemas/registry-org/update-registry-org-request.json b/schemas/registry-org/update-registry-org-request.json index 456be9213..f171addee 100644 --- a/schemas/registry-org/update-registry-org-request.json +++ b/schemas/registry-org/update-registry-org-request.json @@ -101,21 +101,27 @@ "contact_info": { "type": "object", "properties": { - "phone": { - "type": "string" - }, - "poc": { - "type": "string" + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true }, - "poc_email": { - "type": "string", - "format": "email" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true }, - "website": { - "type": "string", - "format": "uri" + "phone": { + "type": "string" } - } + }, + "additionalProperties": false }, "advisory_locations": { "type": "array", @@ -196,4 +202,4 @@ "description": "Additional partner metadata (restricted)" } } -} \ No newline at end of file +} diff --git a/schemas/registry-org/update-registry-org-response.json b/schemas/registry-org/update-registry-org-response.json index 2a5e2cdcb..33a498cf7 100644 --- a/schemas/registry-org/update-registry-org-response.json +++ b/schemas/registry-org/update-registry-org-response.json @@ -115,26 +115,27 @@ "contact_info": { "type": "object", "properties": { - "phone": { - "type": "string" - }, - "poc": { - "type": "string" + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true }, - "poc_email": { - "type": "string", - "format": "email" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true }, - "website": { - "type": "string", - "format": "uri" + "phone": { + "type": "string" } }, - "required": [ - "poc", - "poc_email", - "admins" - ] + "additionalProperties": false }, "advisory_locations": { "type": "array", @@ -173,4 +174,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/controller/audit.controller/audit.controller.js b/src/controller/audit.controller/audit.controller.js index dc1c8c8a5..fdf6555ee 100644 --- a/src/controller/audit.controller/audit.controller.js +++ b/src/controller/audit.controller/audit.controller.js @@ -99,8 +99,7 @@ async function createAuditDocumentForOrg (req, res, next) { audit_uuid: returnValue.uuid }) } catch (err) { - await session.abortTransaction() - throw err + console.error('REAL ERROR WAS:', err.stack); try { await session.abortTransaction() } catch(e) {}; throw err } finally { await session.endSession() } diff --git a/src/controller/glossary.controller/index.js b/src/controller/glossary.controller/index.js index 8c374131b..6d097b5e3 100644 --- a/src/controller/glossary.controller/index.js +++ b/src/controller/glossary.controller/index.js @@ -2,17 +2,13 @@ const router = require('express').Router() const controller = require('./glossary.controller') const mw = require('../../middleware/middleware') -// Get all glossary items - SEC only +// Get all glossary items router.get('/glossary', /* #swagger.tags = ['Glossary'] #swagger.operationId = 'glossaryAll' - #swagger.summary = "Retrieves all glossary items (accessible to Secretariat only)" - #swagger.description = " -

Access Control

-

User must belong to an organization with the Secretariat role

-

Expected Behavior

-

Secretariat: Retrieves all glossary items

" + #swagger.summary = "Retrieves all glossary items" + #swagger.description = "

Retrieves all glossary items

" #swagger.parameters['$ref'] = [ '#/components/parameters/apiEntityHeader', '#/components/parameters/apiUserHeader', @@ -54,21 +50,16 @@ router.get('/glossary', } */ mw.validateUser, - mw.onlySecretariat, controller.getAllGlossaryItems ) -// Get glossary item by services_short_name - SEC only +// Get glossary item by services_short_name router.get('/glossary/:services_short_name', /* #swagger.tags = ['Glossary'] #swagger.operationId = 'glossarySingle' - #swagger.summary = "Retrieves a single glossary item by its short name (accessible to Secretariat only)" - #swagger.description = " -

Access Control

-

User must belong to an organization with the Secretariat role

-

Expected Behavior

-

Secretariat: Retrieves the specified glossary item

" + #swagger.summary = "Retrieves a single glossary item by its short name" + #swagger.description = "

Retrieves the specified glossary item

" #swagger.parameters['services_short_name'] = { description: 'The short name of the glossary item' } #swagger.parameters['$ref'] = [ '#/components/parameters/apiEntityHeader', @@ -119,7 +110,6 @@ router.get('/glossary/:services_short_name', } */ mw.validateUser, - mw.onlySecretariat, controller.getGlossaryItem ) diff --git a/src/controller/org.controller/index.js b/src/controller/org.controller/index.js index 1dd51a767..d69ae7c4a 100644 --- a/src/controller/org.controller/index.js +++ b/src/controller/org.controller/index.js @@ -552,10 +552,9 @@ router.put('/registry/org/:shortname',
  • charter_or_scope
  • product_list
  • disclosure_policy
  • -
  • contact_info.poc
  • -
  • contact_info.poc_email
  • -
  • contact_info.poc_phone
  • -
  • contact_info.org_email
  • +
  • contact_info.websites
  • +
  • contact_info.emails
  • +
  • contact_info.phone
  • partner_role_type
  • partner_country
  • advisory_locations
  • diff --git a/src/controller/org.controller/org.middleware.js b/src/controller/org.controller/org.middleware.js index 1e986bb6e..931c01a5e 100644 --- a/src/controller/org.controller/org.middleware.js +++ b/src/controller/org.controller/org.middleware.js @@ -78,10 +78,9 @@ function validateCreateOrgParameters () { 'charter_or_scope', 'disclosure_policy', 'product_list', - 'contact_info.poc', - 'contact_info.poc_email', + 'contact_info.websites', + 'contact_info.emails', 'contact_info.phone', - 'contact_info.website', '', '', 'partner_role_type', @@ -136,16 +135,16 @@ function validateCreateOrgParameters () { 'aliases', 'hard_quota', 'contact_info.phone', - 'contact_info.website', + 'contact_info.websites', + 'contact_info.emails', 'contact_info', 'users', 'charter_or_scope', 'disclosure_policy', 'product_list', - 'contact_info.poc', - 'contact_info.poc_email', + 'contact_info.websites', + 'contact_info.emails', 'contact_info.phone', - 'contact_info.website', 'private_contacts', 'partner_role_type', 'partner_number', @@ -231,10 +230,9 @@ function validateUpdateOrgParameters () { 'charter_or_scope', 'disclosure_policy', 'product_list', - 'contact_info.poc', - 'contact_info.poc_email', + 'contact_info.websites', + 'contact_info.emails', 'contact_info.phone', - 'contact_info.website', '', '', 'partner_role_type', @@ -325,10 +323,9 @@ const QUERY_PARAMETERS = { 'product_list', 'oversees', 'contact_info', - 'contact_info.poc', - 'contact_info.poc_email', + 'contact_info.websites', + 'contact_info.emails', 'contact_info.phone', - 'contact_info.website', '', '', 'partner_role_type', diff --git a/src/controller/registry-org.controller/registry-org.middleware.js b/src/controller/registry-org.controller/registry-org.middleware.js index 939897911..88319d131 100644 --- a/src/controller/registry-org.controller/registry-org.middleware.js +++ b/src/controller/registry-org.controller/registry-org.middleware.js @@ -15,7 +15,7 @@ function parsePostParams (req, res, next) { 'top_level_root', 'users', 'charter_or_scope', 'disclosure_policy', 'product_list', 'soft_quota', 'hard_quota', - 'private_contacts', 'contact_info.poc', 'contact_info.poc_email', 'contact_info.phone', 'contact_info.website', + 'private_contacts', 'contact_info.websites', 'contact_info.emails', 'contact_info.phone', 'partner_role_type', 'partner_number', 'partner_country', diff --git a/src/middleware/schemas/BaseOrg.json b/src/middleware/schemas/BaseOrg.json index a87e55fe4..b1982cfcb 100644 --- a/src/middleware/schemas/BaseOrg.json +++ b/src/middleware/schemas/BaseOrg.json @@ -100,24 +100,24 @@ "$ref": "#/definitions/uuidType" } }, - "poc": { - "type": "string" + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "uniqueItems": true }, - "poc_email": { - "type": "string", - "format": "email" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "uniqueItems": true }, - "poc_phone": { + "phone": { "type": "string" - }, - "org_email": { - "type": "string", - "format": "email" - }, - "website": { - "$ref": "#/definitions/uriType", - "type": "string", - "pattern": "^(ftp|http)s?://\\S+$" } }, "additionalProperties": false diff --git a/src/model/baseorg.js b/src/model/baseorg.js index 13777a5af..48a5205aa 100644 --- a/src/model/baseorg.js +++ b/src/model/baseorg.js @@ -15,10 +15,9 @@ const schema = { users: { type: [String], set: toUndefined }, admins: [String], contact_info: { - phone: String, - poc: String, - poc_email: String, - website: String + websites: [String], + emails: [String], + phone: String }, private_contacts: [{ _id: false, diff --git a/src/repositories/baseOrgRepository.js b/src/repositories/baseOrgRepository.js index 3b1afc328..1bd9500aa 100644 --- a/src/repositories/baseOrgRepository.js +++ b/src/repositories/baseOrgRepository.js @@ -708,11 +708,9 @@ class BaseOrgRepository extends BaseRepository { * @param {string[]} [incomingParameters.product_list] - A list of the organization's products. (Registry only) * @param {string[]} [incomingParameters.oversees] - A list of short names of organizations this org oversees. (Registry only) * @param {string} [incomingParameters.reports_to] - The short name of the organization this org reports to. (Registry only) - * @param {string} [incomingParameters.contact_info.poc] - The primary point of contact's name. (Registry only) - * @param {string} [incomingParameters.contact_info.poc_email] - The primary point of contact's email. (Registry only) - * @param {string} [incomingParameters.contact_info.poc_phone] - The primary point of contact's phone number. (Registry only) - * @param {string} [incomingParameters.contact_info.org_email] - The general organization email address. (Registry only) - * @param {string} [incomingParameters.contact_info.website] - The organization's website URL. (Registry only) + * @param {string[]} [incomingParameters.contact_info.websites] - The organization's website URLs. (Registry only) + * @param {string[]} [incomingParameters.contact_info.emails] - The organization's email addresses. (Registry only) + * @param {string} [incomingParameters.contact_info.phone] - The organization's phone number. (Registry only) * @param {string} [incomingParameters.cna_role_type] - (Registry only) * @param {string} [incomingParameters.cna_country] - (Registry only) * @param {string[]} [incomingParameters.advisory_locations] - (Registry only) diff --git a/src/scripts/migrate.js b/src/scripts/migrate.js index ad72a2875..e4a8ffdea 100644 --- a/src/scripts/migrate.js +++ b/src/scripts/migrate.js @@ -110,12 +110,9 @@ async function addCVEBoard (db) { hard_quota: null, private_contacts: [], contact_info: { - poc: null, - poc_email: null, - poc_phone: null, - admins: [], - org_email: null, - website: null + phone: null, + emails: [], + websites: [] }, inUse: null, created: null, @@ -216,11 +213,9 @@ async function orgHelper (db) { admins: admins, private_contacts: [], // don't have now contact_info: { - poc: null, // don't have now - poc_email: null, // don't have now - poc_phone: null, // don't have now - org_email: email, - website: site + emails: email ? [email] : [], + websites: site ? [site] : [], + phone: null }, inUse: doc.inUse, created: doc.time.created, diff --git a/test/integration-tests/constants.js b/test/integration-tests/constants.js index df85f8051..1d3c343d0 100644 --- a/test/integration-tests/constants.js +++ b/test/integration-tests/constants.js @@ -381,10 +381,9 @@ const testRegistryOrg = { short_name: 'test_registry_org', long_name: 'Test Registry Organization', contact_info: { - poc: 'Dave', - poc_email: 'dave@test.org', - phone: '555-1234', - website: 'https://test.org' + websites: ['https://test.org'], + emails: ['dave@test.org'], + phone: '555-1234' }, private_contacts: [{ poc: 'Dave Private', @@ -399,10 +398,9 @@ const testRegistryOrg2 = { short_name: 'test_registry_org2', long_name: 'Test Registry Organization2', contact_info: { - poc: 'Dave', - poc_email: 'dave@test.org', - phone: '555-1234', - website: 'https://test.org' + websites: ['https://test.org'], + emails: ['dave@test.org'], + phone: '555-1234' }, authority: ['CNA'], hard_quota: 100000 @@ -426,10 +424,9 @@ const existingRegistryOrg = { short_name: 'win_5', long_name: 'Test Registry Organization', contact_info: { - poc: 'Dave', - poc_email: 'dave@test.org', - phone: '555-1234', - website: 'https://test.org' + websites: ['https://test.org'], + emails: ['dave@test.org'], + phone: '555-1234' }, authority: ['CNA'], hard_quota: 100000 diff --git a/test/integration-tests/org/postOrgTest.js b/test/integration-tests/org/postOrgTest.js index 5f11e07d5..209ec984a 100644 --- a/test/integration-tests/org/postOrgTest.js +++ b/test/integration-tests/org/postOrgTest.js @@ -60,7 +60,7 @@ describe('Testing Org post endpoint', () => { expect(res.body.created.long_name).to.equal(constants.testRegistryOrg.long_name) expect(res.body.created).to.haveOwnProperty('contact_info') - expect(res.body.created.contact_info).to.include(constants.testRegistryOrg.contact_info) + expect(res.body.created.contact_info).to.deep.equal(constants.testRegistryOrg.contact_info) expect(res.body.created).to.haveOwnProperty('private_contacts') expect(res.body.created.private_contacts).to.deep.equal(constants.testRegistryOrg.private_contacts) diff --git a/test/integration-tests/registry-org/registryOrgWithJointReviewTest.js b/test/integration-tests/registry-org/registryOrgWithJointReviewTest.js index db236a830..bbcd6f41d 100644 --- a/test/integration-tests/registry-org/registryOrgWithJointReviewTest.js +++ b/test/integration-tests/registry-org/registryOrgWithJointReviewTest.js @@ -116,7 +116,7 @@ describe('Testing Joint approval', () => { await chai.request(app) .put('/api/registry/org/non_secretariat_org') .set(nonAdminHeaders) - .send({ ...testRegistryOrgForReview, short_name: 'new_non_secretariat_org', contact_info: { website: 'https://www.example.com' } }) + .send({ ...testRegistryOrgForReview, short_name: 'new_non_secretariat_org', contact_info: { websites: ['https://www.example.com'] } }) .then((res) => { expect(res).to.have.status(200) expect(res.body.message).to.contain('organization was successfully updated, but joint approval is required for some fields.') @@ -144,11 +144,11 @@ describe('Testing Joint approval', () => { expect(err).to.be.undefined expect(res).to.have.status(200) expect(res.body.short_name).to.equal('non_secretariat_org') - expect(res.body.contact_info.website).to.equal('https://www.example.com') + expect(res.body.contact_info.websites[0]).to.equal('https://www.example.com') }) }) it('Secretariat can approve the ORG review with body parameter', async function () { - const newBody = { short_name: 'final_non_secretariat_org', contact_info: { website: 'https://final.example.com' }, hard_quota: 1000, authority: ['CNA'], long_name: 'Final Non Secretariat Organization' } + const newBody = { short_name: 'final_non_secretariat_org', contact_info: { websites: ['https://final.example.com'] }, hard_quota: 1000, authority: ['CNA'], long_name: 'Final Non Secretariat Organization' } await chai.request(app) .put(`/api/review/${reviewUUID}/approve`) .set(secretariatHeaders) @@ -164,7 +164,7 @@ describe('Testing Joint approval', () => { expect(err).to.be.undefined expect(res).to.have.status(200) expect(res.body.short_name).to.equal('final_non_secretariat_org') - expect(res.body.contact_info.website).to.equal('https://final.example.com') + expect(res.body.contact_info.websites[0]).to.equal('https://final.example.com') }) }) }) @@ -219,7 +219,7 @@ describe('Testing Joint approval', () => { await chai.request(app) .put('/api/registry/org/non_with_comments') .set(nonAdminHeaders2) - .send({ ...testRegistryOrgForReviewWithComments, short_name: 'new_non_with_comments', contact_info: { website: 'https://www.example.com' } }) + .send({ ...testRegistryOrgForReviewWithComments, short_name: 'new_non_with_comments', contact_info: { websites: ['https://www.example.com'] } }) .then((res) => { expect(res).to.have.status(200) expect(res.body.message).to.contain('organization was successfully updated, but joint approval is required for some fields.') @@ -247,7 +247,7 @@ describe('Testing Joint approval', () => { expect(err).to.be.undefined expect(res).to.have.status(200) expect(res.body.short_name).to.equal('non_with_comments') - expect(res.body.contact_info.website).to.equal('https://www.example.com') + expect(res.body.contact_info.websites[0]).to.equal('https://www.example.com') }) }) it('Secretariat leaves a public comment on the org review', async () => { diff --git a/test/integration-tests/registry-org/verifyDeepRemoveEmpty.js b/test/integration-tests/registry-org/verifyDeepRemoveEmpty.js index d2c056768..c88959459 100644 --- a/test/integration-tests/registry-org/verifyDeepRemoveEmpty.js +++ b/test/integration-tests/registry-org/verifyDeepRemoveEmpty.js @@ -14,8 +14,7 @@ const testNullRemovalOrg = { authority: ['CNA'], hard_quota: 1000, contact_info: { - website: null, // Should be removed - org_email: undefined // Should be removed (or not present) + phone: null // Should be removed } } @@ -40,14 +39,13 @@ describe('Testing Deep Remove Empty in Create Org', () => { expect(createdOrg).to.haveOwnProperty('short_name') expect(createdOrg.short_name).to.equal(testNullRemovalOrg.short_name) - // Verify contact_info exists but does NOT contain website or org_email + // Verify contact_info exists but does NOT contain websites or emails // Ideally if contact_info becomes empty, deepRemoveEmpty might remove the whole object if it recurses well. // Let's check what happened. if (createdOrg.contact_info) { - expect(createdOrg.contact_info).to.not.have.property('website') - expect(createdOrg.contact_info).to.not.have.property('org_email') - // If deepRemoveEmpty works on nested empty objects, contact_info might be gone or empty. - expect(Object.keys(createdOrg.contact_info)).to.be.empty + expect(createdOrg.contact_info).to.not.have.property('phone') + expect(createdOrg.contact_info).to.have.property('websites').that.is.an('array') + expect(createdOrg.contact_info).to.have.property('emails').that.is.an('array') } else { // This is also acceptable if deepRemoveEmpty removes empty objects expect(createdOrg).to.not.have.property('contact_info') diff --git a/test/integration-tests/review-object/reviewObjectTest.js b/test/integration-tests/review-object/reviewObjectTest.js index 3d9c10e46..508354051 100644 --- a/test/integration-tests/review-object/reviewObjectTest.js +++ b/test/integration-tests/review-object/reviewObjectTest.js @@ -199,14 +199,14 @@ describe('Review Object Controller Integration Tests', () => { updateData.long_name = 'Approve Test Organization' updateData.authority = ['CNA'] updateData.hard_quota = 1000 - updateData.contact_info = { website: 'https://www.example.com' } + updateData.contact_info = { websites: ['https://www.example.com'] } const res = await chai .request(app) .put(`/api/registry/org/${constants.existingOrg.short_name}`) .set({ ...constants.nonSecretariatUserHeaders2 }) .send(updateData) expect(res).to.have.status(200) - expect(res.body.updated.contact_info.website).to.equal('https://www.example.com') + expect(res.body.updated.contact_info.websites[0]).to.equal('https://www.example.com') const reviewRes = await chai .request(app) @@ -216,7 +216,7 @@ describe('Review Object Controller Integration Tests', () => { expect(reviewRes.body).to.have.property('uuid') expect(reviewRes.body.status).to.equal('pending') expect(reviewRes.body).to.have.nested.property('new_review_data.long_name', 'Approve Test Organization') - expect(reviewRes.body).to.have.nested.property('new_review_data.contact_info.website', 'https://www.example.com') + expect(reviewRes.body.new_review_data.contact_info.websites[0]).to.equal('https://www.example.com') approveTestReviewUUID = reviewRes.body.uuid }) From 922bce48d30886a9b82f9b9185eb09fcc4dfae90 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Thu, 7 May 2026 11:22:20 -0400 Subject: [PATCH 2/7] charter_or_scope should be a string --- src/middleware/schemas/CNAOrg.json | 2 +- test/integration-tests/registry-org/registryOrgCRUDTest.js | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/middleware/schemas/CNAOrg.json b/src/middleware/schemas/CNAOrg.json index 966056f75..55e0211cf 100644 --- a/src/middleware/schemas/CNAOrg.json +++ b/src/middleware/schemas/CNAOrg.json @@ -30,7 +30,7 @@ "maximum": 100000 }, "charter_or_scope": { - "$ref": "/BaseOrg#/definitions/uriType" + "type": "string" }, "disclosure_policy": { "$ref": "/BaseOrg#/definitions/uriType" diff --git a/test/integration-tests/registry-org/registryOrgCRUDTest.js b/test/integration-tests/registry-org/registryOrgCRUDTest.js index 6f6ec4823..52ca111e5 100644 --- a/test/integration-tests/registry-org/registryOrgCRUDTest.js +++ b/test/integration-tests/registry-org/registryOrgCRUDTest.js @@ -16,7 +16,8 @@ const testRegistryOrg = { partner_role_type: 'Vendor', partner_number: 'Initial Partner Number', partner_country: 'US', - advisory_locations: ['https://example.com/advisories'] + advisory_locations: ['https://example.com/advisories'], + charter_or_scope: 'This is a normal string, not a URI' } let createdOrg @@ -63,6 +64,9 @@ describe('Testing /registryOrg endpoints', () => { expect(res.body.created).to.haveOwnProperty('advisory_locations') expect(res.body.created.advisory_locations).to.deep.equal(testRegistryOrg.advisory_locations) + expect(res.body.created).to.haveOwnProperty('charter_or_scope') + expect(res.body.created.charter_or_scope).to.equal(testRegistryOrg.charter_or_scope) + expect(res.body.created).to.haveOwnProperty('program_data') expect(res.body.created.program_data.status).to.equal('inactive') expect(res.body.created.program_data).to.haveOwnProperty('partner_inactive_date') From bf5170b0b8d345228eaaa61a35eff2ca4ef88720 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Thu, 7 May 2026 12:34:56 -0400 Subject: [PATCH 3/7] Org admins can now see latest open review. --- .../review-object.controller/index.js | 2 +- .../review-object.controller.js | 10 ++++ .../review-object/reviewObjectTest.js | 47 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/controller/review-object.controller/index.js b/src/controller/review-object.controller/index.js index daf8a7a74..8dfbecc01 100644 --- a/src/controller/review-object.controller/index.js +++ b/src/controller/review-object.controller/index.js @@ -146,7 +146,7 @@ router.get('/review/org/:identifier', */ mw.useRegistry(), mw.validateUser, - mw.onlySecretariat, + mw.onlySecretariatOrAdmin, controller.getReviewObjectByOrgIdentifier ) diff --git a/src/controller/review-object.controller/review-object.controller.js b/src/controller/review-object.controller/review-object.controller.js index 7de67c58d..b30a17e94 100644 --- a/src/controller/review-object.controller/review-object.controller.js +++ b/src/controller/review-object.controller/review-object.controller.js @@ -20,6 +20,16 @@ async function getReviewObjectByOrgIdentifier (req, res, next) { return res.status(400).json({ message: 'Missing identifier parameter' }) } let value + + if (!isSecretariat) { + const orgUUID = await orgRepo.getOrgUUID(req.ctx.org) + if (identifierIsUUID && identifier !== orgUUID) { + return res.status(403).json({ error: 'NOT_SAME_ORG_OR_SECRETARIAT', message: 'This information can only be viewed by the users of the same organization or the Secretariat.' }) + } else if (!identifierIsUUID && identifier !== req.ctx.org) { + return res.status(403).json({ error: 'NOT_SAME_ORG_OR_SECRETARIAT', message: 'This information can only be viewed by the users of the same organization or the Secretariat.' }) + } + } + // We may want this to be something different, but for now we are just testing if (identifierIsUUID) { value = await repo.getOrgReviewObjectByOrgUUID(identifier, isSecretariat, {}) diff --git a/test/integration-tests/review-object/reviewObjectTest.js b/test/integration-tests/review-object/reviewObjectTest.js index 508354051..63a91bfc4 100644 --- a/test/integration-tests/review-object/reviewObjectTest.js +++ b/test/integration-tests/review-object/reviewObjectTest.js @@ -13,6 +13,7 @@ describe('Review Object Controller Integration Tests', () => { let rejectTestReviewUUID let autoApproveReviewUUID let autoRejectReviewUUID + let adminRetrievalTestReviewUUID context('Positive Tests', () => { it('Creates an organization to use for review object tests', async () => { @@ -429,6 +430,52 @@ describe('Review Object Controller Integration Tests', () => { expect(reviewRes.body).to.have.property('status', 'rejected') }) // ------------------------------------------------------------------------------------------------ + + it('Org Admin can retrieve their pending review object by org identifier (short_name)', async () => { + const updateData = { + short_name: constants.existingOrg.short_name, + long_name: 'Admin Retrieval Test Org', + authority: ['CNA'], + hard_quota: 1000 + } + const res = await chai + .request(app) + .put(`/api/registry/org/${constants.existingOrg.short_name}`) + .set({ ...constants.nonSecretariatUserHeaders2 }) + .send(updateData) + expect(res).to.have.status(200) + + const reviewRes = await chai + .request(app) + .get(`/api/review/org/${constants.existingOrg.short_name}`) + .set({ ...constants.nonSecretariatUserHeaders2 }) + + expect(reviewRes).to.have.status(200) + expect(reviewRes.body).to.have.property('uuid') + expect(reviewRes.body.status).to.equal('pending') + expect(reviewRes.body).to.have.nested.property('new_review_data.long_name', 'Admin Retrieval Test Org') + + adminRetrievalTestReviewUUID = reviewRes.body.uuid + }) + + it('Org Admin can retrieve their review object by UUID', async () => { + const reviewRes = await chai + .request(app) + .get(`/api/review/byUUID/${adminRetrievalTestReviewUUID}`) + .set({ ...constants.nonSecretariatUserHeaders2 }) + + expect(reviewRes).to.have.status(200) + expect(reviewRes.body).to.have.property('uuid', adminRetrievalTestReviewUUID) + expect(reviewRes.body.status).to.equal('pending') + expect(reviewRes.body).to.have.nested.property('new_review_data.long_name', 'Admin Retrieval Test Org') + + const rejectRes = await chai + .request(app) + .put(`/api/review/${adminRetrievalTestReviewUUID}/reject`) + .set({ ...constants.headers }) + .send({}) + expect(rejectRes).to.have.status(200) + }) }) context('Negative Tests', () => { From 68fab53cec791ac75dda49cfdd8a8e6bbfed4f45 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Thu, 7 May 2026 13:09:50 -0400 Subject: [PATCH 4/7] Audit will be only for secretariat --- src/controller/audit.controller/audit.controller.js | 2 +- src/controller/audit.controller/index.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controller/audit.controller/audit.controller.js b/src/controller/audit.controller/audit.controller.js index fdf6555ee..dd3103a2d 100644 --- a/src/controller/audit.controller/audit.controller.js +++ b/src/controller/audit.controller/audit.controller.js @@ -99,7 +99,7 @@ async function createAuditDocumentForOrg (req, res, next) { audit_uuid: returnValue.uuid }) } catch (err) { - console.error('REAL ERROR WAS:', err.stack); try { await session.abortTransaction() } catch(e) {}; throw err + console.error('REAL ERROR WAS:', err.stack); try { await session.abortTransaction() } catch (e) {}; throw err } finally { await session.endSession() } diff --git a/src/controller/audit.controller/index.js b/src/controller/audit.controller/index.js index 10da8f70f..07930c35c 100644 --- a/src/controller/audit.controller/index.js +++ b/src/controller/audit.controller/index.js @@ -29,14 +29,14 @@ router.get('/audit/org/document/:document_uuid', // Get audit by org identifier (Secretariat or Admin) router.get('/audit/org/:org_identifier', mw.validateUser, - mw.onlySecretariatOrAdmin, + mw.onlySecretariat, auditMw.parseGetParams, controller.AUDIT_GET_BY_ORG_IDENTIFIER ) // Get last X changes (Secretariat or Org Admin) router.get('/audit/org/:org_identifier/:number_of_changes', - mw.onlySecretariatOrAdmin, + mw.onlySecretariat, mw.validateUser, auditMw.parseGetParams, controller.AUDIT_GET_LAST From 0c7695eafce376cf36ffa19630f2fe16451247b4 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Thu, 7 May 2026 13:39:13 -0400 Subject: [PATCH 5/7] org admins should have users uuids --- .../registry-org.controller.js | 2 +- src/repositories/conversationRepository.js | 2 +- src/repositories/reviewObjectRepository.js | 4 +- .../review-object/reviewObjectTest.js | 42 +++++++++++++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/controller/registry-org.controller/registry-org.controller.js b/src/controller/registry-org.controller/registry-org.controller.js index e66646d5a..802f71f12 100644 --- a/src/controller/registry-org.controller/registry-org.controller.js +++ b/src/controller/registry-org.controller/registry-org.controller.js @@ -717,7 +717,7 @@ async function editConversationForOrg (req, res, next) { // Make the edit returnValue = await conversationRepo.editConversation(conversation.UUID, incomingParameters, { session }) - if (!isSecretariat && returnValue) { + if (!isSecretariat && returnValue && returnValue.author_role === 'Secretariat') { delete returnValue.author_id } await session.commitTransaction() diff --git a/src/repositories/conversationRepository.js b/src/repositories/conversationRepository.js index b4ef2e437..a7a18221e 100644 --- a/src/repositories/conversationRepository.js +++ b/src/repositories/conversationRepository.js @@ -44,7 +44,7 @@ class ConversationRepository extends BaseRepository { } }) return conversations.map(convo => convo.toObject()).filter(conv => isSecretariat || conv.visibility === 'public').map(conv => { - if (!isSecretariat) { + if (!isSecretariat && conv.author_role === 'Secretariat') { delete conv.author_id } return conv diff --git a/src/repositories/reviewObjectRepository.js b/src/repositories/reviewObjectRepository.js index 19730b6ae..843f654a2 100644 --- a/src/repositories/reviewObjectRepository.js +++ b/src/repositories/reviewObjectRepository.js @@ -248,7 +248,9 @@ class ReviewObjectRepository extends BaseRepository { // If non-secretariat, remove author_id if (!isSecretariat) { conversations = conversations.map(c => { - delete c.author_id + if (c.author_role === 'Secretariat') { + delete c.author_id + } return c }) } diff --git a/test/integration-tests/review-object/reviewObjectTest.js b/test/integration-tests/review-object/reviewObjectTest.js index 63a91bfc4..e499cac63 100644 --- a/test/integration-tests/review-object/reviewObjectTest.js +++ b/test/integration-tests/review-object/reviewObjectTest.js @@ -458,6 +458,48 @@ describe('Review Object Controller Integration Tests', () => { adminRetrievalTestReviewUUID = reviewRes.body.uuid }) + it('Org Admin can see Partner UUIDs in conversation but not Secretariat UUIDs', async () => { + // Get the target UUID (Org UUID) for win_5 + const orgRes = await chai.request(app) + .get(`/api/registry/org/${constants.existingOrg.short_name}`) + .set({ ...constants.headers }) + const targetUUID = orgRes.body.UUID + + // 1. Secretariat posts a conversation message + const secMessage = { body: 'Secretariat message', visibility: 'public' } + let res = await chai.request(app) + .post(`/api/conversation/target/${targetUUID}`) + .set(constants.headers) + .send(secMessage) + expect(res).to.have.status(200) + + // 2. Org Admin posts a conversation message + const adminMessage = { body: 'Admin message' } + res = await chai.request(app) + .post(`/api/conversation/target/${targetUUID}`) + .set(constants.nonSecretariatUserHeaders2) // They are Partner + .send(adminMessage) + expect(res).to.have.status(200) + + // 3. Org Admin fetches the review object to see conversations + const reviewRes = await chai.request(app) + .get(`/api/review/byUUID/${adminRetrievalTestReviewUUID}`) + .set(constants.nonSecretariatUserHeaders2) + + expect(reviewRes).to.have.status(200) + expect(reviewRes.body).to.have.property('conversation') + expect(reviewRes.body.conversation).to.be.an('array') + + const secConvo = reviewRes.body.conversation.find(c => c.author_role === 'Secretariat') + const adminConvo = reviewRes.body.conversation.find(c => c.author_role === 'Partner') + + expect(secConvo).to.exist + expect(secConvo).to.not.have.property('author_id') // Secretariat UUID hidden + + expect(adminConvo).to.exist + expect(adminConvo).to.have.property('author_id') // Partner UUID visible + }) + it('Org Admin can retrieve their review object by UUID', async () => { const reviewRes = await chai .request(app) From 9687813441c14e7e112e1e16c746bc3381522e86 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Thu, 7 May 2026 14:11:07 -0400 Subject: [PATCH 6/7] Also remove author_name --- .../registry-org.controller.js | 1 + src/repositories/conversationRepository.js | 1 + src/repositories/reviewObjectRepository.js | 1 + .../review-object/reviewObjectTest.js | 14 ++++++++------ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/controller/registry-org.controller/registry-org.controller.js b/src/controller/registry-org.controller/registry-org.controller.js index 802f71f12..d32c8577a 100644 --- a/src/controller/registry-org.controller/registry-org.controller.js +++ b/src/controller/registry-org.controller/registry-org.controller.js @@ -719,6 +719,7 @@ async function editConversationForOrg (req, res, next) { returnValue = await conversationRepo.editConversation(conversation.UUID, incomingParameters, { session }) if (!isSecretariat && returnValue && returnValue.author_role === 'Secretariat') { delete returnValue.author_id + delete returnValue.author_name } await session.commitTransaction() } catch (error) { diff --git a/src/repositories/conversationRepository.js b/src/repositories/conversationRepository.js index a7a18221e..047de1c41 100644 --- a/src/repositories/conversationRepository.js +++ b/src/repositories/conversationRepository.js @@ -46,6 +46,7 @@ class ConversationRepository extends BaseRepository { return conversations.map(convo => convo.toObject()).filter(conv => isSecretariat || conv.visibility === 'public').map(conv => { if (!isSecretariat && conv.author_role === 'Secretariat') { delete conv.author_id + delete conv.author_name } return conv }) diff --git a/src/repositories/reviewObjectRepository.js b/src/repositories/reviewObjectRepository.js index 843f654a2..401aa8c42 100644 --- a/src/repositories/reviewObjectRepository.js +++ b/src/repositories/reviewObjectRepository.js @@ -250,6 +250,7 @@ class ReviewObjectRepository extends BaseRepository { conversations = conversations.map(c => { if (c.author_role === 'Secretariat') { delete c.author_id + delete c.author_name } return c }) diff --git a/test/integration-tests/review-object/reviewObjectTest.js b/test/integration-tests/review-object/reviewObjectTest.js index e499cac63..762315287 100644 --- a/test/integration-tests/review-object/reviewObjectTest.js +++ b/test/integration-tests/review-object/reviewObjectTest.js @@ -469,35 +469,37 @@ describe('Review Object Controller Integration Tests', () => { const secMessage = { body: 'Secretariat message', visibility: 'public' } let res = await chai.request(app) .post(`/api/conversation/target/${targetUUID}`) - .set(constants.headers) + .set({ ...constants.headers }) .send(secMessage) expect(res).to.have.status(200) // 2. Org Admin posts a conversation message - const adminMessage = { body: 'Admin message' } + const adminMessage = { body: 'Admin message' } res = await chai.request(app) .post(`/api/conversation/target/${targetUUID}`) - .set(constants.nonSecretariatUserHeaders2) // They are Partner + .set({ ...constants.nonSecretariatUserHeaders2 }) // They are Partner .send(adminMessage) expect(res).to.have.status(200) // 3. Org Admin fetches the review object to see conversations const reviewRes = await chai.request(app) .get(`/api/review/byUUID/${adminRetrievalTestReviewUUID}`) - .set(constants.nonSecretariatUserHeaders2) - + .set({ ...constants.nonSecretariatUserHeaders2 }) + expect(reviewRes).to.have.status(200) expect(reviewRes.body).to.have.property('conversation') expect(reviewRes.body.conversation).to.be.an('array') - + const secConvo = reviewRes.body.conversation.find(c => c.author_role === 'Secretariat') const adminConvo = reviewRes.body.conversation.find(c => c.author_role === 'Partner') expect(secConvo).to.exist expect(secConvo).to.not.have.property('author_id') // Secretariat UUID hidden + expect(secConvo).to.not.have.property('author_name') // Secretariat name hidden expect(adminConvo).to.exist expect(adminConvo).to.have.property('author_id') // Partner UUID visible + expect(adminConvo).to.have.property('author_name') // Partner name visible }) it('Org Admin can retrieve their review object by UUID', async () => { From 81c8e968dafd98262fabb2f5c5d6482fc478b778 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Thu, 7 May 2026 14:50:51 -0400 Subject: [PATCH 7/7] Added more glossary definitions --- datadump/pre-population/glossary.json | 88 +++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/datadump/pre-population/glossary.json b/datadump/pre-population/glossary.json index ac9ccc4e7..10ee659ce 100644 --- a/datadump/pre-population/glossary.json +++ b/datadump/pre-population/glossary.json @@ -1,7 +1,83 @@ [ - { - "services_short_name": "long_name", - "label": "Long Name", - "def": "The full, official name of an organization participating in the CVE program." - } -] + { + "services_short_name": "long_name", + "label": "Long Name", + "def": "Partner long name displayed on the Partners list on website" + }, + { + "services_short_name": "partner_number", + "label": "Partner Number", + "def": "Unique Identifier that provides insight into when the partner joined the program (used for reporting and website updates)" + }, + { + "services_short_name": "short_name", + "label": "Short Name", + "def": "Partner short name, computer readable name, used for API requests and posted with the CVE record." + }, + { + "services_short_name": "status", + "label": "Status", + "def": "Partner status" + }, + { + "services_short_name": "authority", + "label": "Authority", + "def": "Provides the type of partner." + }, + { + "services_short_name": "website_update_date", + "label": "CVE Website Update Date", + "def": "Date Partner information was last updated on the website." + }, + { + "services_short_name": "cve_website_update_needed", + "label": "CVE Website Update Needed", + "def": "Tracks if partner information updates are completed or pending." + }, + { + "services_short_name": "top_level_root", + "label": "Top Level Root", + "def": "Provides the CNA Top Level Root." + }, + { + "services_short_name": "reports_to", + "label": "Reports To", + "def": "Provides who the partner reports to." + }, + { + "services_short_name": "partner_country", + "label": "Partner Country", + "def": "Partner country that is self identified." + }, + { + "services_short_name": "partner_active_date", + "label": "Partner Active Date", + "def": "Date the partner joined the program." + }, + { + "services_short_name": "partner_inactive_date", + "label": "Partner Inactive Date", + "def": "Date the partner was removed from the program." + }, + { + "services_short_name": "charter_or_scope", + "label": "Charter or Scope", + "def": "Partner charter or scope." + }, + { + "services_short_name": "disclosure_policy", + "label": "Disclosure Policy", + "def": "Partner disclosure policy." + }, + { + "services_short_name": "advisory_location", + "label": "Advisory Location", + "def": "Partner vulnerability advisory locations." + }, + { + "services_short_name": "vulnerability_advisory_location_for_web_scraping", + "label": "Vulnerability Advisory Locations for Web Scraping.", + "def": "Partner vulnerability advisory location for web scraping." + } + ] +