ccs-digitalmarketplace-frameworks 3.11.0 → 3.11.2
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/.github/workflows/test.yml +2 -2
- package/.pre-commit-config.yaml +15 -17
- package/.python-version +1 -1
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicDayRate.yml +1 -1
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicDayRateSpecialist.yml +1 -1
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicLocations.yml +2 -2
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicUkDayRate.yml +1 -1
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/chiefDigitalAndDataRolesChiefInformationSecurityOfficerRoles.yml +2 -2
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/multiqChiefDigitalAndDataRolesChiefInformationSecurityOfficerBasic.yml +2 -2
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/multiqChiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicDCDP.yml +3 -3
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/multiqCyberSecurityRolesCyberSecurity.yml +2 -0
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/multiqCyberSecurityRolesCyberSecurityDCDP.yml +2 -0
- package/frameworks/digital-outcomes-and-specialists-7/questions/services/studioLocationPostcode.yml +2 -2
- package/package.json +1 -1
- package/requirements-dev.txt +5 -15
- package/requirements.in +2 -2
- package/requirements.txt +4 -6
- package/schema_generator/validation.py +65 -3
- package/scripts/generate-validation-schemas.py +5 -0
|
@@ -6,7 +6,7 @@ jobs:
|
|
|
6
6
|
strategy:
|
|
7
7
|
fail-fast: false
|
|
8
8
|
matrix:
|
|
9
|
-
python-version: [ '3.
|
|
9
|
+
python-version: [ '3.11' ]
|
|
10
10
|
|
|
11
11
|
steps:
|
|
12
12
|
- uses: actions/checkout@v4
|
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
runs-on: ubuntu-latest
|
|
36
36
|
strategy:
|
|
37
37
|
matrix:
|
|
38
|
-
python-version: [ '3.
|
|
38
|
+
python-version: [ '3.11' ]
|
|
39
39
|
script:
|
|
40
40
|
- scripts/generate-assessment-schema.py g-cloud-14
|
|
41
41
|
- scripts/generate-search-config.py g-cloud-14 services --output-path=/tmp
|
package/.pre-commit-config.yaml
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
# See https://pre-commit.com/hooks.html for more hooks
|
|
1
|
+
---
|
|
3
2
|
repos:
|
|
4
|
-
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
)
|
|
3
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
4
|
+
rev: v5.0.0
|
|
5
|
+
hooks:
|
|
6
|
+
- id: trailing-whitespace
|
|
7
|
+
- id: end-of-file-fixer
|
|
8
|
+
- id: check-yaml
|
|
9
|
+
- id: check-added-large-files
|
|
10
|
+
- id: detect-private-key
|
|
11
|
+
|
|
12
|
+
- repo: https://github.com/PyCQA/flake8
|
|
13
|
+
rev: 7.0.0
|
|
14
|
+
hooks:
|
|
15
|
+
- id: flake8
|
|
16
|
+
pass_filenames: false
|
package/.python-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.11
|
|
@@ -20,7 +20,7 @@ digit_limits:
|
|
|
20
20
|
validations:
|
|
21
21
|
- name: answer_required
|
|
22
22
|
field: chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicPriceMax
|
|
23
|
-
message: Enter the amount you will charge for a chief
|
|
23
|
+
message: Enter the amount you will charge for a chief information security officer
|
|
24
24
|
- name: not_money_format
|
|
25
25
|
field: chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicPriceMax
|
|
26
26
|
message: Maximum price must be a number less than 10,000, without units, like 99.95
|
|
@@ -20,7 +20,7 @@ digit_limits:
|
|
|
20
20
|
validations:
|
|
21
21
|
- name: answer_required
|
|
22
22
|
field: chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicPriceMax
|
|
23
|
-
message: Enter the amount you will charge for a chief
|
|
23
|
+
message: Enter the amount you will charge for a chief information security officer
|
|
24
24
|
- name: not_money_format
|
|
25
25
|
field: chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicPriceMax
|
|
26
26
|
message: Maximum price must be a number less than 10,000, without units, like 99.95
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
name: Where will your chief
|
|
1
|
+
name: Where will your chief information security officer work?
|
|
2
2
|
question: |
|
|
3
|
-
<p class="govuk-!-margin-bottom-2"><span class="govuk-fieldset__legend--s">Where will your chief
|
|
3
|
+
<p class="govuk-!-margin-bottom-2"><span class="govuk-fieldset__legend--s">Where will your chief information security officer work?</span></p>
|
|
4
4
|
<p class="govuk-!-margin-bottom-0"><span class="govuk-fieldset__legend--s">Choose all the locations where the specialist can work at buyer’s sites, and whether they can work offsite.</span></p>
|
|
5
5
|
hint: |
|
|
6
6
|
‘Offsite’ means the supplier will not be working at the buyer’s own sites.
|
|
@@ -20,7 +20,7 @@ digit_limits:
|
|
|
20
20
|
validations:
|
|
21
21
|
- name: answer_required
|
|
22
22
|
field: chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicUkPriceMax
|
|
23
|
-
message: Enter the amount you will charge for a chief
|
|
23
|
+
message: Enter the amount you will charge for a chief information security officer
|
|
24
24
|
- name: not_money_format
|
|
25
25
|
field: chiefDigitalAndDataRolesChiefInformationSecurityOfficerBasicUkPriceMax
|
|
26
26
|
message: Maximum price must be a number less than 10,000, without units, like 99.95
|
|
@@ -10,9 +10,9 @@ depends:
|
|
|
10
10
|
type: checkboxes
|
|
11
11
|
|
|
12
12
|
options:
|
|
13
|
-
- label: Chief
|
|
13
|
+
- label: Chief information security officer
|
|
14
14
|
value: basic
|
|
15
|
-
description: <a class="govuk-link" target="_blank" rel="noopener noreferrer" href="https://ddat-capability-framework.service.gov.uk/role/chief-information-security-officer#chief-
|
|
15
|
+
description: <a class="govuk-link" target="_blank" rel="noopener noreferrer" href="https://ddat-capability-framework.service.gov.uk/role/chief-information-security-officer#chief-information-security-officer">View role description <span class="govuk-visually-hidden">for Chief information security officer </span>(opens in new tab)</a>
|
|
16
16
|
|
|
17
17
|
followup:
|
|
18
18
|
multiqChiefDigitalAndDataRolesChiefInformationSecurityOfficerBasic:
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
name: Chief
|
|
2
|
-
question: Chief
|
|
1
|
+
name: Chief information security officer
|
|
2
|
+
question: Chief information security officer
|
|
3
3
|
question_advice:
|
|
4
4
|
<p>
|
|
5
|
-
<a class="govuk-link" target="_blank" rel="noopener noreferrer" href="https://ddat-capability-framework.service.gov.uk/role/chief-information-security-officer#chief-
|
|
5
|
+
<a class="govuk-link" target="_blank" rel="noopener noreferrer" href="https://ddat-capability-framework.service.gov.uk/role/chief-information-security-officer#chief-information-security-officer">View role description <span class="govuk-visually-hidden">for Chief information security officer </span>(opens in new tab)</a>.
|
|
6
6
|
</p>
|
|
7
7
|
<p>
|
|
8
8
|
Framework maximum rates are fixed for the duration of the agreement.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
name: Cyber security
|
|
2
2
|
question: Cyber security
|
|
3
|
+
hint:
|
|
4
|
+
The role is responsible for protecting an organisation's systems, networks, and data from unauthorised access, cyberattacks, and security breaches. Individuals in these roles perform a variety of tasks that involve identifying potential threats, responding and recovering from incidents, and ensuring that appropriate security measures are in place to safeguard critical information.
|
|
3
5
|
|
|
4
6
|
depends:
|
|
5
7
|
- "on": lot
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
name: Cyber security
|
|
2
2
|
question: Cyber security
|
|
3
|
+
hint:
|
|
4
|
+
The role is responsible for protecting an organisation's systems, networks, and data from unauthorised access, cyberattacks, and security breaches. Individuals in these roles perform a variety of tasks that involve identifying potential threats, responding and recovering from incidents, and ensuring that appropriate security measures are in place to safeguard critical information.
|
|
3
5
|
|
|
4
6
|
depends:
|
|
5
7
|
- "on": lot
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccs-digitalmarketplace-frameworks",
|
|
3
|
-
"version": "3.11.
|
|
3
|
+
"version": "3.11.2",
|
|
4
4
|
"description": "Data files for Digital Marketplace’s procurement frameworks",
|
|
5
5
|
"repository": "git@github.com:Crown-Commercial-Service/ccs-digitalmarketplace-frameworks",
|
|
6
6
|
"author": "enquiries@digitalmarketplace.service.gov.uk"
|
package/requirements-dev.txt
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
#
|
|
2
|
-
# This file is autogenerated by pip-compile with Python 3.
|
|
2
|
+
# This file is autogenerated by pip-compile with Python 3.11
|
|
3
3
|
# by the following command:
|
|
4
4
|
#
|
|
5
5
|
# pip-compile requirements-dev.in
|
|
6
6
|
#
|
|
7
|
-
async-timeout==4.0.3
|
|
8
|
-
# via
|
|
9
|
-
# -r requirements.txt
|
|
10
|
-
# redis
|
|
11
7
|
attrs==23.1.0
|
|
12
8
|
# via
|
|
13
9
|
# hypothesis
|
|
@@ -30,13 +26,13 @@ cachelib==0.13.0
|
|
|
30
26
|
# via
|
|
31
27
|
# -r requirements.txt
|
|
32
28
|
# flask-session
|
|
33
|
-
ccs-digitalmarketplace-apiclient==
|
|
29
|
+
ccs-digitalmarketplace-apiclient==28.0.0
|
|
34
30
|
# via
|
|
35
31
|
# -r requirements.txt
|
|
36
32
|
# ccs-digitalmarketplace-utils
|
|
37
|
-
ccs-digitalmarketplace-content-loader==
|
|
33
|
+
ccs-digitalmarketplace-content-loader==13.0.0
|
|
38
34
|
# via -r requirements.txt
|
|
39
|
-
ccs-digitalmarketplace-utils==
|
|
35
|
+
ccs-digitalmarketplace-utils==69.0.0
|
|
40
36
|
# via
|
|
41
37
|
# -r requirements.txt
|
|
42
38
|
# ccs-digitalmarketplace-content-loader
|
|
@@ -76,10 +72,6 @@ docopt==0.6.2
|
|
|
76
72
|
# via
|
|
77
73
|
# -r requirements.txt
|
|
78
74
|
# notifications-python-client
|
|
79
|
-
exceptiongroup==1.1.3
|
|
80
|
-
# via
|
|
81
|
-
# hypothesis
|
|
82
|
-
# pytest
|
|
83
75
|
flake8==7.1.1
|
|
84
76
|
# via -r requirements-dev.in
|
|
85
77
|
flask==3.0.3
|
|
@@ -116,7 +108,7 @@ govuk-country-register==0.5.0
|
|
|
116
108
|
# via
|
|
117
109
|
# -r requirements.txt
|
|
118
110
|
# ccs-digitalmarketplace-utils
|
|
119
|
-
hypothesis==6.
|
|
111
|
+
hypothesis==6.119.3
|
|
120
112
|
# via -r requirements-dev.in
|
|
121
113
|
idna==3.7
|
|
122
114
|
# via
|
|
@@ -238,8 +230,6 @@ six==1.16.0
|
|
|
238
230
|
# python-dateutil
|
|
239
231
|
sortedcontainers==2.3.0
|
|
240
232
|
# via hypothesis
|
|
241
|
-
tomli==2.0.1
|
|
242
|
-
# via pytest
|
|
243
233
|
unicodecsv==0.14.1
|
|
244
234
|
# via
|
|
245
235
|
# -r requirements.txt
|
package/requirements.in
CHANGED
package/requirements.txt
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
#
|
|
2
|
-
# This file is autogenerated by pip-compile with Python 3.
|
|
2
|
+
# This file is autogenerated by pip-compile with Python 3.11
|
|
3
3
|
# by the following command:
|
|
4
4
|
#
|
|
5
5
|
# pip-compile requirements.in
|
|
6
6
|
#
|
|
7
|
-
async-timeout==4.0.3
|
|
8
|
-
# via redis
|
|
9
7
|
blinker==1.8.2
|
|
10
8
|
# via flask
|
|
11
9
|
boto3==1.34.144
|
|
@@ -16,11 +14,11 @@ botocore==1.34.144
|
|
|
16
14
|
# s3transfer
|
|
17
15
|
cachelib==0.13.0
|
|
18
16
|
# via flask-session
|
|
19
|
-
ccs-digitalmarketplace-apiclient==
|
|
17
|
+
ccs-digitalmarketplace-apiclient==28.0.0
|
|
20
18
|
# via ccs-digitalmarketplace-utils
|
|
21
|
-
ccs-digitalmarketplace-content-loader==
|
|
19
|
+
ccs-digitalmarketplace-content-loader==13.0.0
|
|
22
20
|
# via -r requirements.in
|
|
23
|
-
ccs-digitalmarketplace-utils==
|
|
21
|
+
ccs-digitalmarketplace-utils==69.0.0
|
|
24
22
|
# via
|
|
25
23
|
# -r requirements.in
|
|
26
24
|
# ccs-digitalmarketplace-content-loader
|
|
@@ -29,6 +29,10 @@ MANIFESTS = {
|
|
|
29
29
|
'question_set': 'additional-lot-questions',
|
|
30
30
|
'manifest': 'evaluations'
|
|
31
31
|
},
|
|
32
|
+
'assign-evaluations': {
|
|
33
|
+
'question_set': 'additional-lot-questions',
|
|
34
|
+
'manifest': 'evaluations'
|
|
35
|
+
},
|
|
32
36
|
'agreements': {
|
|
33
37
|
'question_set': 'agreements',
|
|
34
38
|
'manifest': 'agreement'
|
|
@@ -231,6 +235,17 @@ SCHEMAS = {
|
|
|
231
235
|
"user-research-studios-and-participants",
|
|
232
236
|
],
|
|
233
237
|
),
|
|
238
|
+
'assign-evaluations': _get_schema_title_and_slugs(
|
|
239
|
+
"Assign evaluation framework lot questions",
|
|
240
|
+
"digital-outcomes-and-specialists",
|
|
241
|
+
exclude_lots=[
|
|
242
|
+
"digital-outcomes",
|
|
243
|
+
"digital-specialists",
|
|
244
|
+
"user-research-studios",
|
|
245
|
+
"user-research-participants",
|
|
246
|
+
"user-research-studios-and-participants",
|
|
247
|
+
],
|
|
248
|
+
),
|
|
234
249
|
'additional-lot-questions': _get_schema_title_and_slugs(
|
|
235
250
|
"Additional lot questions",
|
|
236
251
|
"digital-outcomes-and-specialists",
|
|
@@ -262,7 +277,7 @@ SCHEMAS = {
|
|
|
262
277
|
}
|
|
263
278
|
|
|
264
279
|
|
|
265
|
-
def
|
|
280
|
+
def _load_manifest(schema_type, framework_slug, lot_slug_or_agreement_version):
|
|
266
281
|
loader = ContentLoader('./')
|
|
267
282
|
print(
|
|
268
283
|
f'{framework_slug}/{lot_slug_or_agreement_version} '
|
|
@@ -281,15 +296,25 @@ def load_questions(schema_type, framework_slug, lot_slug_or_agreement_version):
|
|
|
281
296
|
else:
|
|
282
297
|
filter_key = 'lot'
|
|
283
298
|
|
|
284
|
-
|
|
299
|
+
return loader.get_manifest(framework_slug, MANIFESTS[schema_type]['manifest']).filter(
|
|
285
300
|
{filter_key: lot_slug_or_agreement_version},
|
|
286
301
|
dynamic=False,
|
|
287
302
|
ignore_depends_on_follow_up=True
|
|
288
303
|
)
|
|
289
304
|
|
|
305
|
+
|
|
306
|
+
def load_questions(schema_type, framework_slug, lot_slug_or_agreement_version):
|
|
307
|
+
manifest = _load_manifest(schema_type, framework_slug, lot_slug_or_agreement_version)
|
|
308
|
+
|
|
290
309
|
return {q['id']: q for q in sum((s.questions for s in manifest.sections), [])}
|
|
291
310
|
|
|
292
311
|
|
|
312
|
+
def load_sections(schema_type, framework_slug, lot_slug_or_agreement_version):
|
|
313
|
+
manifest = _load_manifest(schema_type, framework_slug, lot_slug_or_agreement_version)
|
|
314
|
+
|
|
315
|
+
return {s['slug']: s for s in manifest.sections}
|
|
316
|
+
|
|
317
|
+
|
|
293
318
|
def merge_schemas(a, b):
|
|
294
319
|
if not (isinstance(a, dict) and isinstance(b, dict)):
|
|
295
320
|
raise TypeError("Error merging unsupported types '{}' and '{}'".format(
|
|
@@ -986,7 +1011,7 @@ def _multiquestion_dependencies(questions):
|
|
|
986
1011
|
return {'dependencies': dependencies} if dependencies else {}
|
|
987
1012
|
|
|
988
1013
|
|
|
989
|
-
def
|
|
1014
|
+
def _generate_question_schema(schema_type, schema_name, framework_slug, lot_slug):
|
|
990
1015
|
questions = load_questions(schema_type, framework_slug, lot_slug)
|
|
991
1016
|
drop_non_schema_questions(questions)
|
|
992
1017
|
schema = empty_schema(schema_name)
|
|
@@ -998,6 +1023,43 @@ def generate_schema(schema_type, schema_name, framework_slug, lot_slug):
|
|
|
998
1023
|
return schema
|
|
999
1024
|
|
|
1000
1025
|
|
|
1026
|
+
def _generate_assign_evaluations_schema(schema_type, schema_name, framework_slug, lot_slug):
|
|
1027
|
+
sections = load_sections(schema_type, framework_slug, lot_slug)
|
|
1028
|
+
schema = empty_schema(schema_name)
|
|
1029
|
+
|
|
1030
|
+
schema['properties'].update({
|
|
1031
|
+
"evaluatorFrameworkLots": {
|
|
1032
|
+
"type": "array",
|
|
1033
|
+
"items": {
|
|
1034
|
+
"type": "integer"
|
|
1035
|
+
}
|
|
1036
|
+
},
|
|
1037
|
+
"frameworkSlug": {
|
|
1038
|
+
"type": "string",
|
|
1039
|
+
},
|
|
1040
|
+
"lotSlug": {
|
|
1041
|
+
"type": "string",
|
|
1042
|
+
},
|
|
1043
|
+
"sectionSlug": {
|
|
1044
|
+
"enum": list(sections)
|
|
1045
|
+
}
|
|
1046
|
+
})
|
|
1047
|
+
|
|
1048
|
+
schema['required'].extend(schema['properties'].keys())
|
|
1049
|
+
schema['required'].sort()
|
|
1050
|
+
|
|
1051
|
+
return schema
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
def generate_schema(schema_type, schema_name, framework_slug, lot_slug):
|
|
1055
|
+
if schema_type == 'assign-evaluations':
|
|
1056
|
+
generate_schema_method = _generate_assign_evaluations_schema
|
|
1057
|
+
else:
|
|
1058
|
+
generate_schema_method = _generate_question_schema
|
|
1059
|
+
|
|
1060
|
+
return generate_schema_method(schema_type, schema_name, framework_slug, lot_slug)
|
|
1061
|
+
|
|
1062
|
+
|
|
1001
1063
|
def generate_schema_todir(dir_path, schema_type, schema_name, framework_slug, lot_slug):
|
|
1002
1064
|
start_t = time.perf_counter()
|
|
1003
1065
|
schema = generate_schema(schema_type, schema_name, framework_slug, lot_slug)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
Usage:
|
|
5
5
|
generate-validation-schemas.py --output-path=<output_path> [--framework=<framework_slug>] [--lot=<lot_slug>]
|
|
6
|
+
[--manifest=<manifest>]
|
|
6
7
|
|
|
7
8
|
"""
|
|
8
9
|
import os
|
|
@@ -22,6 +23,7 @@ if __name__ == '__main__':
|
|
|
22
23
|
OUTPUT_DIR = arguments['--output-path']
|
|
23
24
|
FRAMEWORK_SLUG = arguments.get('--framework')
|
|
24
25
|
LOT_SLUG = arguments.get('--lot')
|
|
26
|
+
MANIFEST = arguments.get('--manifest')
|
|
25
27
|
if not os.path.exists(OUTPUT_DIR):
|
|
26
28
|
print("Creating {} directory".format(OUTPUT_DIR))
|
|
27
29
|
os.makedirs(OUTPUT_DIR)
|
|
@@ -34,6 +36,9 @@ if __name__ == '__main__':
|
|
|
34
36
|
if LOT_SLUG:
|
|
35
37
|
schemas = [schema for schema in schemas if schema[3] == LOT_SLUG]
|
|
36
38
|
|
|
39
|
+
if MANIFEST:
|
|
40
|
+
schemas = [schema for schema in schemas if schema[0] == MANIFEST]
|
|
41
|
+
|
|
37
42
|
with Pool(processes=5) as pool:
|
|
38
43
|
results = pool.starmap(
|
|
39
44
|
partial(
|