@slicedearth/whoisleuth-cli 2.6.0 → 2.7.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.
Files changed (84) hide show
  1. package/DISCLOSURE +8 -5
  2. package/NOTICE +3 -2
  3. package/README.md +60 -67
  4. package/cli/artifact-validation/case-response.mjs +6 -857
  5. package/cli/artifact-validation/lookup-evidence.mjs +15 -2
  6. package/cli/artifact-verify.mjs +32 -1
  7. package/cli/case-command.mjs +17 -17
  8. package/cli/case-pack.mjs +7 -1
  9. package/cli/ci-report.mjs +17 -5
  10. package/cli/command-definition.mjs +5 -5
  11. package/cli/doctor.mjs +37 -3
  12. package/cli/formatters/html.mjs +3 -0
  13. package/cli/formatters/json.mjs +8 -1
  14. package/cli/formatters/terminal-lookup.mjs +24 -1
  15. package/cli/history-command-definitions.mjs +1 -1
  16. package/cli/investigation-plan.mjs +15 -0
  17. package/cli/lookup-brief.mjs +11 -5
  18. package/cli/lookup-command-runner.mjs +20 -13
  19. package/cli/review-command-definitions.mjs +11 -11
  20. package/cli/saved-lookup.mjs +22 -7
  21. package/cli/source-reliability.mjs +12 -10
  22. package/cli/support-arguments.mjs +1 -1
  23. package/cli/support-command-definitions.mjs +5 -4
  24. package/cli/support-command-runner.mjs +6 -4
  25. package/cli/workflow-command-definitions.mjs +2 -1
  26. package/docs/cli-reference.md +49 -11
  27. package/docs/cli.md +109 -32
  28. package/docs/contextual-reviews.md +10 -0
  29. package/docs/infrastructure-observations.md +9 -0
  30. package/lib/dmarc-discovery.mjs +4 -2
  31. package/lib/dns-inheritance-review.mjs +14 -1
  32. package/lib/evidence-export.mjs +10 -4
  33. package/lib/evidence-report.mjs +2 -1
  34. package/lib/generated/cisa-kev-catalog.mjs +17 -4
  35. package/lib/generated/registrar-standing-catalogue.mjs +7 -7
  36. package/lib/generated/retire-browser-catalog.mjs +178 -5
  37. package/lib/idn-confusables.mjs +5 -1
  38. package/lib/lookup-collection-receipt.mjs +52 -0
  39. package/lib/lookup-diagnostics.mjs +2 -12
  40. package/lib/lookup-progress.mjs +29 -31
  41. package/lib/lookup-response-contract.mjs +9 -0
  42. package/lib/lookup-response.mjs +15 -14
  43. package/lib/lookup-source-progress.mjs +4 -2
  44. package/lib/lookup.mjs +33 -2
  45. package/lib/rdap-capabilities.mjs +43 -9
  46. package/lib/registry-insights.mjs +17 -6
  47. package/lib/sslbl-certificates.generated.mjs +143 -142
  48. package/lib/whois-authority.mjs +56 -1
  49. package/lib/whois-chain.mjs +2 -1
  50. package/lib/whois-contracts.mjs +2 -0
  51. package/lib/whois-normalization.mjs +4 -4
  52. package/package.json +6 -6
  53. package/packages/analysis/bounded-json.mjs +12 -2
  54. package/packages/cases/case-attachment-model.mjs +36 -1
  55. package/packages/cases/case-checkpoint-receipts.mjs +68 -0
  56. package/packages/cases/case-evidence-links.mjs +28 -0
  57. package/packages/cases/case-evidence-model.mjs +39 -6
  58. package/packages/cases/case-migration-model.mjs +9 -1
  59. package/packages/cases/case-object-coverage.mjs +106 -20
  60. package/packages/cases/case-record-operations.mjs +13 -0
  61. package/packages/cases/case-record-projection.mjs +28 -2
  62. package/packages/cases/case-report.mjs +5 -4
  63. package/packages/cases/case-response-packet-validation.mjs +880 -0
  64. package/packages/cases/case-response-packet-vocabulary.mjs +12 -1
  65. package/packages/cases/case-response-packet.mjs +2 -15
  66. package/packages/cases/case-response-review-inputs.mjs +18 -1
  67. package/packages/cases/case-type-presentation.mjs +10 -0
  68. package/packages/cases/case-workflow-metadata.mjs +0 -8
  69. package/packages/comparison/capture-context.mjs +3 -2
  70. package/packages/contracts/analyst-review-state-contract.mjs +1 -1
  71. package/packages/contracts/case-portability.mjs +59 -28
  72. package/packages/contracts/cli-doctor.mjs +4 -0
  73. package/packages/contracts/cli-lookup.mjs +57 -46
  74. package/packages/contracts/lookup-evidence.mjs +12 -2
  75. package/packages/contracts/registry-insights.mjs +6 -0
  76. package/packages/evidence/dmarc-policy-context.mjs +80 -0
  77. package/packages/evidence/lookup-collection-receipt.mjs +140 -0
  78. package/packages/evidence/lookup-collection-review.mjs +74 -0
  79. package/packages/interchange/external-findings-import.mjs +8 -4
  80. package/packages/investigation/bulk-mail-exposure.mjs +2 -2
  81. package/packages/investigation/domain-history-review.mjs +7 -1
  82. package/packages/workspace/brand-keyword-campaign.mjs +11 -1
  83. package/packages/workspace/bulk-session-model.mjs +8 -0
  84. package/third-party-notices.txt +29 -29
@@ -1,4 +1,3 @@
1
- // Response packet vocabulary shared by construction and independent validation.
2
1
  export const RESPONSE_CONTACT_KINDS = [
3
2
  'registrar',
4
3
  'registry',
@@ -6,6 +5,18 @@ export const RESPONSE_CONTACT_KINDS = [
6
5
  'security_txt',
7
6
  'application_platform',
8
7
  ];
8
+ const ACTION_CONTACT_KINDS = {
9
+ registrar_report: 'registrar',
10
+ registry_report: 'registry',
11
+ network_hosting_report: 'network_hosting',
12
+ security_contact_report: 'security_txt',
13
+ platform_report: 'application_platform',
14
+ defensive_control: 'manual',
15
+ internal_review: 'manual',
16
+ };
17
+ export function responseActionContactKind(type) {
18
+ return ACTION_CONTACT_KINDS[type];
19
+ }
9
20
  export const RESPONSE_PACKET_PROFILE_IDS = [
10
21
  'registrar',
11
22
  'registry',
@@ -1,5 +1,5 @@
1
1
  import { renderCaseResponsePacket } from "./case-response-packet-render.mjs";
2
- import { responseContactLabel as contactLabel } from "./case-response-packet-vocabulary.mjs";
2
+ import { responseActionContactKind, responseContactLabel as contactLabel } from "./case-response-packet-vocabulary.mjs";
3
3
  // Pure abuse-evidence packet builder. It creates local review artifacts only:
4
4
  // no network requests, mailto links, submissions, or provider side effects.
5
5
  import { assertPacketAmendmentSelection } from "./case-requested-evidence.mjs";
@@ -202,19 +202,6 @@ function normalizeLimitations(value) {
202
202
  }
203
203
  return [...unique];
204
204
  }
205
- function actionContactKind(type) {
206
- if (type === 'registrar_report')
207
- return 'registrar';
208
- if (type === 'registry_report')
209
- return 'registry';
210
- if (type === 'network_hosting_report')
211
- return 'network_hosting';
212
- if (type === 'security_contact_report')
213
- return 'security_txt';
214
- if (type === 'platform_report')
215
- return 'application_platform';
216
- return 'manual';
217
- }
218
205
  function selectedPacketAction(caseRecord, input) {
219
206
  const actionId = typeof input.actionId === 'string' && /^[A-Za-z0-9_-]{1,64}$/u.test(input.actionId)
220
207
  ? input.actionId
@@ -264,7 +251,7 @@ function bindPacketRoute(caseRecord, input, generatedAt) {
264
251
  contacts: [],
265
252
  };
266
253
  }
267
- const kind = actionContactKind(action.type);
254
+ const kind = responseActionContactKind(action.type);
268
255
  const compatible = profile.requiredContactKind
269
256
  ? kind === profile.requiredContactKind
270
257
  : profile.id === 'browser_blocklist'
@@ -4,7 +4,7 @@ import { readCaseDeliveryPacketReceipt, readCasePacketCorrection, assertDelivery
4
4
  import { CASE_SELECTED_EVIDENCE_SOURCE_LIMITATION } from "./case-evidence-links.mjs";
5
5
  import { CASE_RESPONSE_REVIEW_INPUTS_SCHEMA, MAX_ABUSE_CATEGORY_LENGTH, MAX_ABUSIVE_URLS, MAX_AFFECTED_PARTY_LENGTH, MAX_CASE_ACTIONS, MAX_CASE_ACTION_EVENTS_PER_ACTION, MAX_CASE_ACTION_EVENTS_PER_CASE, MAX_EXACT_URL_LENGTH, MAX_RESPONSE_ACTION_HISTORY, MAX_RESPONSE_ARTEFACT_REFERENCES, MAX_RESPONSE_CONTACTS, MAX_RESPONSE_CONTRADICTIONS, MAX_RESPONSE_HARM_LENGTH, MAX_RESPONSE_LIMITATIONS, MAX_RESPONSE_LIMITATION_LENGTH, MAX_RESPONSE_REFERENCE_LENGTH, MAX_RESPONSE_SELECTED_EVIDENCE, MAX_RESPONSE_VALUE_LENGTH, PUBLISHED_V2_2_CASE_RESPONSE_REVIEW_INPUTS_VERSION, PUBLISHED_V2_3_CASE_RESPONSE_REVIEW_INPUTS_VERSION, SUPPORTED_CASE_RESPONSE_REVIEW_INPUTS_VERSIONS, } from "../contracts/case-portability.mjs";
6
6
  import { CASE_ACTION_EVENT_SOURCE_CLASSES, CASE_ACTION_STATES, CASE_ACTION_TYPES, CASE_ASSERTION_STATES, CASE_CLOSURE_REASONS, CASE_OBSERVED_EFFECT_SOURCE_CLASSES, CASE_OBSERVED_EFFECT_STATES, CASE_PIN_COMPLETENESS, CASE_PROVIDER_OUTCOMES, } from "./case-response-records.mjs";
7
- import { RESPONSE_CONTACT_KINDS, RESPONSE_PACKET_PROFILE_IDS, RESPONSE_READINESS_ROW_IDS, RESPONSE_READINESS_STATES, } from "./case-response-packet-vocabulary.mjs";
7
+ import { RESPONSE_CONTACT_KINDS, RESPONSE_PACKET_PROFILE_IDS, RESPONSE_READINESS_ROW_IDS, RESPONSE_READINESS_STATES, responseActionContactKind, } from "./case-response-packet-vocabulary.mjs";
8
8
  import { isValidAsciiHostname } from "../contracts/domain-name.mjs";
9
9
  import { readCaseResponseObject, readCaseResponseObjects, readCaseResponseObjectOutcome, assertCaseObjectOutcome } from "./case-response-object.mjs";
10
10
  const CONTACT_KINDS = new Set(RESPONSE_CONTACT_KINDS);
@@ -142,6 +142,21 @@ function recursivelyFreezeReviewValue(value) {
142
142
  }
143
143
  return Object.freeze(value);
144
144
  }
145
+ /** Compare already shape-validated route and action records without rebuilding
146
+ * or normalising the retained evidence. Older formats omit the review deadline. */
147
+ export function assertCaseResponseRecipientAction(route, actions, hasReviewAfter) {
148
+ if (!route)
149
+ return;
150
+ const action = actions.find(candidate => candidate.actionId === route.actionId);
151
+ if (!action
152
+ || route.kind !== responseActionContactKind(action.type)
153
+ || route.contact !== action.recipient
154
+ || route.source !== (action.contactSource || 'analyst supplied')
155
+ || route.observedAt !== action.routeObservedAt
156
+ || (hasReviewAfter && route.reviewAfter !== action.routeReviewAfter)) {
157
+ throw new TypeError('Case-response recipient route must match its selected action.');
158
+ }
159
+ }
145
160
  export function validateCaseResponseReviewInputs(value) {
146
161
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
147
162
  throw new TypeError('Case-response review inputs must be an exact object.');
@@ -404,6 +419,8 @@ export function validateCaseResponseReviewInputs(value) {
404
419
  || escalationActionIds.some((id, index) => currentLineageActionIds?.[index] !== id))) {
405
420
  throw new TypeError('Case-response escalation history must match the selected action lineage in order.');
406
421
  }
422
+ if (hasActionBinding)
423
+ assertCaseResponseRecipientAction(source.recipientRoute, source.escalationHistory, hasPlatformRoutes);
407
424
  reviewCount(source.escalationHistoryOmitted, MAX_CASE_ACTIONS, 'Case-response omitted action count');
408
425
  if (version >= 5)
409
426
  assertPacketAmendmentSelection(source.escalationHistory.map(action => ({
@@ -0,0 +1,10 @@
1
+ import { caseTypeRecords } from "./case-workflow-metadata.mjs";
2
+ /** Display text for declared Case types; admission and mutation remain separate. */
3
+ export function caseTypeSummary(record) {
4
+ const labels = caseTypeRecords(record).map((item) => item.label);
5
+ if (!labels.length)
6
+ return '';
7
+ if (labels.length <= 2)
8
+ return labels.join(' and ');
9
+ return `${labels.slice(0, 2).join(', ')} and ${labels.length - 2} more`;
10
+ }
@@ -44,14 +44,6 @@ export function caseTypeRecords(record) {
44
44
  const selected = new Set(caseTypeIds(record));
45
45
  return CASE_TYPES.filter((item) => selected.has(item.id));
46
46
  }
47
- export function caseTypeSummary(record) {
48
- const labels = caseTypeRecords(record).map((item) => item.label);
49
- if (!labels.length)
50
- return '';
51
- if (labels.length <= 2)
52
- return labels.join(' and ');
53
- return `${labels.slice(0, 2).join(', ')} and ${labels.length - 2} more`;
54
- }
55
47
  function encodeCaseReference(value, minimumLength) {
56
48
  let remainder = value;
57
49
  let encoded = '';
@@ -1,6 +1,7 @@
1
1
  import { exact, text } from "../evidence/artifact-structure.mjs";
2
2
  import { normalizeExplicitIsoTimestamp } from "../evidence/observation.mjs";
3
3
  import { readEvidenceImageDimensions } from "../evidence/image-regions.mjs";
4
+ export const MAX_CAPTURE_COMPARISON_CONTEXTS = 20;
4
5
  /** Optional declarations remain unknown for existing manifests; no inference from image dimensions. */
5
6
  export function readCaptureConditions(raw) {
6
7
  if (raw === undefined || raw === null)
@@ -23,8 +24,8 @@ export function readObservationLabel(raw) {
23
24
  return text(raw, 'Observation label', 80);
24
25
  }
25
26
  export function compareObservationContexts(input) {
26
- if (!Array.isArray(input) || input.length < 2 || input.length > 20)
27
- throw new TypeError('Compare between 2 and 20 observation contexts.');
27
+ if (!Array.isArray(input) || input.length < 2 || input.length > MAX_CAPTURE_COMPARISON_CONTEXTS)
28
+ throw new TypeError(`Compare between 2 and ${MAX_CAPTURE_COMPARISON_CONTEXTS} observation contexts.`);
28
29
  const observations = input.map(value => {
29
30
  const observedAt = value.observedAt === null ? null : normalizeExplicitIsoTimestamp(value.observedAt);
30
31
  if (value.observedAt !== null && !observedAt)
@@ -59,7 +59,7 @@ export const ANALYST_REVIEW_NEXT_ACTIONS = ['review', 'refresh', 'follow_up', 'r
59
59
  export const ANALYST_REVIEW_LIFECYCLE_STATES = ['open', 'expected', 'suppressed', 'resolved', 'expired', 'invalidated', 'recurred', 'orphaned'];
60
60
  export const ANALYST_REVIEW_QUEUE_OPTIONS = [
61
61
  { value: 'needs_action', label: 'Needs action' },
62
- { value: 'waiting', label: 'Waiting / follow-up' },
62
+ { value: 'waiting', label: 'Waiting on' },
63
63
  { value: 'changed', label: 'Changed since review' },
64
64
  { value: 'reviewed', label: 'Reviewed' },
65
65
  { value: 'all', label: 'Everything' },
@@ -164,7 +164,8 @@ export const INCIDENT_CASE_SCHEMA_VERSION = 16;
164
164
  export const EVIDENCE_FOLLOW_UP_CASE_SCHEMA_VERSION = 17;
165
165
  export const OBJECT_RESPONSE_CASE_SCHEMA_VERSION = 18;
166
166
  export const DELIVERY_CORRECTION_CASE_SCHEMA_VERSION = 19;
167
- export const CASE_SCHEMA_VERSION = DELIVERY_CORRECTION_CASE_SCHEMA_VERSION;
167
+ export const COLLECTION_RECEIPT_CASE_SCHEMA_VERSION = 20;
168
+ export const CASE_SCHEMA_VERSION = COLLECTION_RECEIPT_CASE_SCHEMA_VERSION;
168
169
  export const CASE_BROWSER_SUPPORTED_VERSIONS = Object.freeze([
169
170
  PUBLIC_CASE_SCHEMA_VERSION,
170
171
  PUBLISHED_V2_CASE_SCHEMA_VERSION,
@@ -173,6 +174,7 @@ export const CASE_BROWSER_SUPPORTED_VERSIONS = Object.freeze([
173
174
  INCIDENT_CASE_SCHEMA_VERSION,
174
175
  EVIDENCE_FOLLOW_UP_CASE_SCHEMA_VERSION,
175
176
  OBJECT_RESPONSE_CASE_SCHEMA_VERSION,
177
+ DELIVERY_CORRECTION_CASE_SCHEMA_VERSION,
176
178
  CASE_SCHEMA_VERSION,
177
179
  ]);
178
180
  export const CASE_IMPORT_VERSIONS = CASE_BROWSER_SUPPORTED_VERSIONS;
@@ -230,7 +232,7 @@ export const SUPPORTED_CASE_RESPONSE_REVIEW_INPUTS_VERSIONS = Object.freeze([
230
232
  ]);
231
233
  export const CLI_CASE_PACK_SCHEMA = 'whoisleuth.cli.case-pack';
232
234
  export const CLI_CASE_PACK_VERSION = 2;
233
- export const CLI_CASE_PACK_WRITER_FIXTURE_ID = 'cli-case-pack-v2-case-v19-current';
235
+ export const CLI_CASE_PACK_WRITER_FIXTURE_ID = `cli-case-pack-v${CLI_CASE_PACK_VERSION}-case-v${CASE_SCHEMA_VERSION}-current`;
234
236
  export const CLI_CASE_PACK_INPUT_CASE_VERSIONS = Object.freeze(CASE_IMPORT_VERSIONS.filter((version) => version >= PUBLISHED_V2_3_CASE_SCHEMA_VERSION));
235
237
  export const SUPPORTED_CLI_CASE_PACK_VERSIONS = Object.freeze([CLI_CASE_PACK_VERSION]);
236
238
  export const CLI_CASE_PACK_ROOT_KEYS = Object.freeze(['version', 'exportedAt', 'cases', 'packet', 'integrity']);
@@ -252,7 +254,7 @@ export const CLI_CASE_PACK_CASE_REPORT_EPOCHS = Object.freeze([
252
254
  Object.freeze({ caseVersions: Object.freeze([INCIDENT_CASE_SCHEMA_VERSION]), reportVersions: Object.freeze([LATEST_PUBLIC_CASE_REPORT_SCHEMA_VERSION]) }),
253
255
  Object.freeze({ caseVersions: Object.freeze([EVIDENCE_FOLLOW_UP_CASE_SCHEMA_VERSION]), reportVersions: Object.freeze([EVIDENCE_FOLLOW_UP_CASE_REPORT_SCHEMA_VERSION]) }),
254
256
  Object.freeze({ caseVersions: Object.freeze([OBJECT_RESPONSE_CASE_SCHEMA_VERSION]), reportVersions: Object.freeze([OBJECT_RESPONSE_CASE_REPORT_SCHEMA_VERSION]) }),
255
- Object.freeze({ caseVersions: Object.freeze([CASE_SCHEMA_VERSION]), reportVersions: Object.freeze([CASE_REPORT_SCHEMA_VERSION]) }),
257
+ Object.freeze({ caseVersions: Object.freeze([DELIVERY_CORRECTION_CASE_SCHEMA_VERSION, COLLECTION_RECEIPT_CASE_SCHEMA_VERSION]), reportVersions: Object.freeze([CASE_REPORT_SCHEMA_VERSION]) }),
256
258
  ]);
257
259
  export function caseReportVersionMatchesCase(caseVersion, reportVersion) {
258
260
  return typeof reportVersion === 'number'
@@ -266,7 +268,7 @@ export const PUBLISHED_V2_WORKSPACE_ARCHIVE_VERSION = 6;
266
268
  export const PUBLISHED_V2_2_WORKSPACE_ARCHIVE_VERSION = 7;
267
269
  export const PUBLISHED_V2_3_WORKSPACE_ARCHIVE_VERSION = 8;
268
270
  export const WORKSPACE_ARCHIVE_VERSION = 10;
269
- export const WORKSPACE_ARCHIVE_WRITER_FIXTURE_ID = 'workspace-archive-v10-case-v19-empty-current';
271
+ export const WORKSPACE_ARCHIVE_WRITER_FIXTURE_ID = `workspace-archive-v${WORKSPACE_ARCHIVE_VERSION}-case-v${CASE_SCHEMA_VERSION}-empty-current`;
270
272
  export const SUPPORTED_WORKSPACE_ARCHIVE_VERSIONS = Object.freeze([
271
273
  PUBLIC_WORKSPACE_ARCHIVE_VERSION,
272
274
  PUBLISHED_V2_WORKSPACE_ARCHIVE_VERSION,
@@ -468,6 +470,35 @@ export function serialiseWorkspaceArchiveSection(value) {
468
470
  return serialised;
469
471
  }
470
472
  const CASE_LIFECYCLE_FIXTURES = Object.freeze([
473
+ Object.freeze({
474
+ id: 'browser-case-v20', path: 'test/fixtures/case-lifecycle/browser-case-v20.json', bytes: 3312,
475
+ sha256: '6dd0fa2d486a746d24c1d2b5dc85a31ff50219e2cb8d0d993b4d35a0ac460977', contentDigestSha256: null,
476
+ schema: CASE_BROWSER_STORE_LIFECYCLE_SCHEMA, version: COLLECTION_RECEIPT_CASE_SCHEMA_VERSION,
477
+ role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null,
478
+ shapeId: 'case.browser-store.v20', scope: 'repository',
479
+ }),
480
+ Object.freeze({
481
+ id: 'case-export-v20', path: 'test/fixtures/case-lifecycle/case-export-v20.json', bytes: 3356,
482
+ sha256: '52e3b852358fd0c3d1f53b2cbe8cab2d5002ed71954c4c9ddc2b7884aa226e22', contentDigestSha256: null,
483
+ schema: CASE_EXPORT_LIFECYCLE_SCHEMA, version: COLLECTION_RECEIPT_CASE_SCHEMA_VERSION,
484
+ role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null,
485
+ shapeId: 'case.export.v20', scope: 'repository',
486
+ }),
487
+ Object.freeze({
488
+ id: 'cli-case-pack-v2-case-v20-current', path: 'test/fixtures/case-lifecycle/cli-case-pack-v2-case-v20-current.json', bytes: 9874,
489
+ sha256: '2cf92058e3c6a84409089a201dfe5aad2cbd74e79bee90327abc75dd45fc1dcf',
490
+ contentDigestSha256: 'sha256:e42dfc160add1defda8d36b1399f6c730b0a9bd4df6128a85f08bdef6c7527f6',
491
+ schema: CLI_CASE_PACK_SCHEMA, version: CLI_CASE_PACK_VERSION,
492
+ role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null,
493
+ shapeId: 'case.cli-pack.current', scope: 'repository',
494
+ }),
495
+ Object.freeze({
496
+ id: 'workspace-archive-v10-case-v20-empty-current', path: 'test/fixtures/case-lifecycle/workspace-archive-v10-case-v20-empty-current.json', bytes: 7616,
497
+ sha256: 'b82005bc4bf7ea855076eefa059f5d39d41633ad5a53d55f49b7413b0fe99f2c', contentDigestSha256: null,
498
+ schema: WORKSPACE_ARCHIVE_SCHEMA, version: WORKSPACE_ARCHIVE_VERSION,
499
+ role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null,
500
+ shapeId: 'case.workspace-archive.v10', scope: 'repository',
501
+ }),
471
502
  Object.freeze({
472
503
  id: 'browser-case-v19',
473
504
  path: 'test/fixtures/case-lifecycle/browser-case-v19.json',
@@ -475,10 +506,10 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
475
506
  sha256: '3d3c3c3f35f05406d5f4d2b9a0925e6971a9dd237f570733a0b1e82a52d99a92',
476
507
  contentDigestSha256: null,
477
508
  schema: CASE_BROWSER_STORE_LIFECYCLE_SCHEMA,
478
- version: CASE_SCHEMA_VERSION,
479
- role: 'current',
480
- expectation: 'accepted_exact',
481
- expectedOutputFixtureId: null,
509
+ version: DELIVERY_CORRECTION_CASE_SCHEMA_VERSION,
510
+ role: 'historical',
511
+ expectation: 'normalises_to_current_output',
512
+ expectedOutputFixtureId: `browser-case-v${CASE_SCHEMA_VERSION}`,
482
513
  shapeId: 'case.browser-store.v19',
483
514
  scope: 'repository',
484
515
  }),
@@ -489,10 +520,10 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
489
520
  sha256: '65cbb4952766cf6016d4ba81b5859a8a2bd16eb373c7c2f6d08d666aa29c99c1',
490
521
  contentDigestSha256: null,
491
522
  schema: CASE_EXPORT_LIFECYCLE_SCHEMA,
492
- version: CASE_SCHEMA_VERSION,
493
- role: 'current',
494
- expectation: 'accepted_exact',
495
- expectedOutputFixtureId: null,
523
+ version: DELIVERY_CORRECTION_CASE_SCHEMA_VERSION,
524
+ role: 'historical',
525
+ expectation: 'normalises_to_current_output',
526
+ expectedOutputFixtureId: `case-export-v${CASE_SCHEMA_VERSION}`,
496
527
  shapeId: 'case.export.v19',
497
528
  scope: 'repository',
498
529
  }),
@@ -553,8 +584,8 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
553
584
  scope: 'repository',
554
585
  }),
555
586
  Object.freeze({
556
- id: WORKSPACE_ARCHIVE_WRITER_FIXTURE_ID,
557
- path: `test/fixtures/case-lifecycle/${WORKSPACE_ARCHIVE_WRITER_FIXTURE_ID}.json`,
587
+ id: 'workspace-archive-v10-case-v19-empty-current',
588
+ path: 'test/fixtures/case-lifecycle/workspace-archive-v10-case-v19-empty-current.json',
558
589
  bytes: 7616,
559
590
  sha256: '4dee9ab450b16a2ab4cf46a4807fd2be81c1809c8dd4641fbef47ffb78b21794',
560
591
  contentDigestSha256: null,
@@ -576,7 +607,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
576
607
  version: PUBLIC_CASE_SCHEMA_VERSION,
577
608
  role: 'historical',
578
609
  expectation: 'normalises_to_current_output',
579
- expectedOutputFixtureId: 'browser-case-v19',
610
+ expectedOutputFixtureId: `browser-case-v${CASE_SCHEMA_VERSION}`,
580
611
  shapeId: `case.browser-store.v${PUBLIC_CASE_SCHEMA_VERSION}`,
581
612
  scope: 'repository',
582
613
  }),
@@ -590,7 +621,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
590
621
  version: PUBLISHED_V2_CASE_SCHEMA_VERSION,
591
622
  role: 'historical',
592
623
  expectation: 'normalises_to_current_output',
593
- expectedOutputFixtureId: 'browser-case-v19',
624
+ expectedOutputFixtureId: `browser-case-v${CASE_SCHEMA_VERSION}`,
594
625
  shapeId: `case.browser-store.v${PUBLISHED_V2_CASE_SCHEMA_VERSION}`,
595
626
  scope: 'repository',
596
627
  }),
@@ -604,7 +635,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
604
635
  version: PUBLISHED_V2_2_CASE_SCHEMA_VERSION,
605
636
  role: 'historical',
606
637
  expectation: 'normalises_to_current_output',
607
- expectedOutputFixtureId: 'browser-case-v19',
638
+ expectedOutputFixtureId: `browser-case-v${CASE_SCHEMA_VERSION}`,
608
639
  shapeId: `case.browser-store.v${PUBLISHED_V2_2_CASE_SCHEMA_VERSION}`,
609
640
  scope: 'repository',
610
641
  }),
@@ -618,7 +649,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
618
649
  version: PUBLISHED_V2_3_CASE_SCHEMA_VERSION,
619
650
  role: 'historical',
620
651
  expectation: 'normalises_to_current_output',
621
- expectedOutputFixtureId: 'browser-case-v19',
652
+ expectedOutputFixtureId: `browser-case-v${CASE_SCHEMA_VERSION}`,
622
653
  shapeId: `case.browser-store.v${PUBLISHED_V2_3_CASE_SCHEMA_VERSION}`,
623
654
  scope: 'repository',
624
655
  }),
@@ -632,7 +663,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
632
663
  version: INCIDENT_CASE_SCHEMA_VERSION,
633
664
  role: 'historical',
634
665
  expectation: 'normalises_to_current_output',
635
- expectedOutputFixtureId: 'browser-case-v19',
666
+ expectedOutputFixtureId: `browser-case-v${CASE_SCHEMA_VERSION}`,
636
667
  shapeId: `case.browser-store.v${INCIDENT_CASE_SCHEMA_VERSION}`,
637
668
  scope: 'repository',
638
669
  }),
@@ -646,7 +677,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
646
677
  version: EVIDENCE_FOLLOW_UP_CASE_SCHEMA_VERSION,
647
678
  role: 'historical',
648
679
  expectation: 'normalises_to_current_output',
649
- expectedOutputFixtureId: 'browser-case-v19',
680
+ expectedOutputFixtureId: `browser-case-v${CASE_SCHEMA_VERSION}`,
650
681
  shapeId: `case.browser-store.v${EVIDENCE_FOLLOW_UP_CASE_SCHEMA_VERSION}`,
651
682
  scope: 'repository',
652
683
  }),
@@ -660,7 +691,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
660
691
  version: OBJECT_RESPONSE_CASE_SCHEMA_VERSION,
661
692
  role: 'historical',
662
693
  expectation: 'normalises_to_current_output',
663
- expectedOutputFixtureId: 'browser-case-v19',
694
+ expectedOutputFixtureId: `browser-case-v${CASE_SCHEMA_VERSION}`,
664
695
  shapeId: `case.browser-store.v${OBJECT_RESPONSE_CASE_SCHEMA_VERSION}`,
665
696
  scope: 'repository',
666
697
  }),
@@ -674,7 +705,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
674
705
  version: PUBLIC_CASE_SCHEMA_VERSION,
675
706
  role: 'historical',
676
707
  expectation: 'normalises_to_current_output',
677
- expectedOutputFixtureId: 'case-export-v19',
708
+ expectedOutputFixtureId: `case-export-v${CASE_SCHEMA_VERSION}`,
678
709
  shapeId: `case.export.v${PUBLIC_CASE_SCHEMA_VERSION}`,
679
710
  scope: 'repository',
680
711
  }),
@@ -688,7 +719,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
688
719
  version: PUBLISHED_V2_CASE_SCHEMA_VERSION,
689
720
  role: 'historical',
690
721
  expectation: 'normalises_to_current_output',
691
- expectedOutputFixtureId: 'case-export-v19',
722
+ expectedOutputFixtureId: `case-export-v${CASE_SCHEMA_VERSION}`,
692
723
  shapeId: `case.export.v${PUBLISHED_V2_CASE_SCHEMA_VERSION}`,
693
724
  scope: 'repository',
694
725
  }),
@@ -702,7 +733,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
702
733
  version: PUBLISHED_V2_2_CASE_SCHEMA_VERSION,
703
734
  role: 'historical',
704
735
  expectation: 'normalises_to_current_output',
705
- expectedOutputFixtureId: 'case-export-v19',
736
+ expectedOutputFixtureId: `case-export-v${CASE_SCHEMA_VERSION}`,
706
737
  shapeId: `case.export.v${PUBLISHED_V2_2_CASE_SCHEMA_VERSION}`,
707
738
  scope: 'repository',
708
739
  }),
@@ -716,7 +747,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
716
747
  version: PUBLISHED_V2_3_CASE_SCHEMA_VERSION,
717
748
  role: 'historical',
718
749
  expectation: 'normalises_to_current_output',
719
- expectedOutputFixtureId: 'case-export-v19',
750
+ expectedOutputFixtureId: `case-export-v${CASE_SCHEMA_VERSION}`,
720
751
  shapeId: `case.export.v${PUBLISHED_V2_3_CASE_SCHEMA_VERSION}`,
721
752
  scope: 'repository',
722
753
  }),
@@ -730,7 +761,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
730
761
  version: INCIDENT_CASE_SCHEMA_VERSION,
731
762
  role: 'historical',
732
763
  expectation: 'normalises_to_current_output',
733
- expectedOutputFixtureId: 'case-export-v19',
764
+ expectedOutputFixtureId: `case-export-v${CASE_SCHEMA_VERSION}`,
734
765
  shapeId: `case.export.v${INCIDENT_CASE_SCHEMA_VERSION}`,
735
766
  scope: 'repository',
736
767
  }),
@@ -744,7 +775,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
744
775
  version: EVIDENCE_FOLLOW_UP_CASE_SCHEMA_VERSION,
745
776
  role: 'historical',
746
777
  expectation: 'normalises_to_current_output',
747
- expectedOutputFixtureId: 'case-export-v19',
778
+ expectedOutputFixtureId: `case-export-v${CASE_SCHEMA_VERSION}`,
748
779
  shapeId: `case.export.v${EVIDENCE_FOLLOW_UP_CASE_SCHEMA_VERSION}`,
749
780
  scope: 'repository',
750
781
  }),
@@ -758,7 +789,7 @@ const CASE_LIFECYCLE_FIXTURES = Object.freeze([
758
789
  version: OBJECT_RESPONSE_CASE_SCHEMA_VERSION,
759
790
  role: 'historical',
760
791
  expectation: 'normalises_to_current_output',
761
- expectedOutputFixtureId: 'case-export-v19',
792
+ expectedOutputFixtureId: `case-export-v${CASE_SCHEMA_VERSION}`,
762
793
  shapeId: `case.export.v${OBJECT_RESPONSE_CASE_SCHEMA_VERSION}`,
763
794
  scope: 'repository',
764
795
  }),
@@ -0,0 +1,4 @@
1
+ export const DOCTOR_SCHEMA = 'whoisleuth.cli.doctor';
2
+ export const DOCTOR_VERSION = 1;
3
+ export const DOCTOR_SUMMARY_SCHEMA = 'whoisleuth.cli.doctor-summary';
4
+ export const DOCTOR_SUMMARY_VERSION = 1;