Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
import testRule from './__helpers__/testRule.js';
import { DiagnosticSeverity } from '@stoplight/types';

testRule('xgen-IPA-121-date-time-fields-mention-iso-8601', [
{
name: 'valid when date-time format mentions ISO 8601 in description',
document: {
components: {
schemas: {
TestSchema: {
properties: {
createdAt: {
type: 'string',
format: 'date-time',
description: 'The creation timestamp in ISO 8601 format in UTC.',
},
updatedOn: {
type: 'string',
format: 'date-time',
description: 'When the resource was last updated. Uses ISO 8601 datetime format in UTC.',
},
},
},
},
parameters: {
TestParameter: {
name: 'createdAt',
in: 'query',
description: 'The creation timestamp in ISO 8601 format in UTC.',
schema: {
type: 'string',
format: 'date-time',
},
},
},
},
},
errors: [],
},
{
name: 'valid with non-date-time format',
document: {
components: {
schemas: {
TestSchema: {
properties: {
username: {
type: 'string',
description: 'The username for login.',
},
age: {
type: 'integer',
description: 'Age in years.',
},
},
},
},
},
},
errors: [],
},
{
name: 'invalid when date-time format has no description',
document: {
components: {
schemas: {
TestSchema: {
properties: {
createdAt: {
type: 'string',
format: 'date-time',
},
modifiedAt: {
type: 'string',
format: 'date-time',
description: 'The modification timestamp.',
},
},
},
},
parameters: {
TestParameter: {
name: 'createdAt',
in: 'query',
description: 'The creation timestamp',
schema: {
type: 'string',
format: 'date-time',
},
},
},
},
paths: {
'/resources': {
post: {
requestBody: {
content: {
'application/json': {
schema: {
properties: {
$ref: '#/components/schemas/TestSchema',
},
},
},
},
},
},
},
},
},
errors: [
{
code: 'xgen-IPA-121-date-time-fields-mention-iso-8601',
message:
'API producers must use ISO 8601 date-time format in UTC for all timestamps. Fields must note ISO 8601 and UTC in their description.',
path: ['components', 'schemas', 'TestSchema', 'properties', 'createdAt'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-121-date-time-fields-mention-iso-8601',
message:
'API producers must use ISO 8601 date-time format in UTC for all timestamps. Fields must note ISO 8601 and UTC in their description.',
path: ['components', 'schemas', 'TestSchema', 'properties', 'modifiedAt'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-121-date-time-fields-mention-iso-8601',
message:
'API producers must use ISO 8601 date-time format in UTC for all timestamps. Fields must note ISO 8601 and UTC in their description.',
path: ['components', 'parameters', 'TestParameter'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'exception',
document: {
components: {
schemas: {
TestSchema: {
properties: {
createdAt: {
type: 'string',
format: 'date-time',
description: 'The creation timestamp.',
'x-xgen-IPA-exception': {
'xgen-IPA-121-date-time-fields-mention-iso-8601': 'Legacy field format',
},
},
},
},
},
parameters: {
TestParameter: {
name: 'createdAt',
in: 'query',
description: 'The creation timestamp',
schema: {
type: 'string',
format: 'date-time',
},
'x-xgen-IPA-exception': {
'xgen-IPA-121-date-time-fields-mention-iso-8601': 'Legacy field format',
},
},
},
},
},
errors: [],
},
{
name: 'test with parameters in path operation',
document: {
paths: {
'/resources': {
get: {
parameters: [
{
name: 'since',
in: 'query',
description: 'Filter resources created since this ISO 8601 timestamp in UTC',
schema: {
type: 'string',
format: 'date-time',
},
},
{
name: 'until',
in: 'query',
description: 'Filter resources created until this timestamp', // Missing ISO 8601 and UTC
schema: {
type: 'string',
format: 'date-time',
},
},
],
},
},
},
},
errors: [
{
code: 'xgen-IPA-121-date-time-fields-mention-iso-8601',
message:
'API producers must use ISO 8601 date-time format in UTC for all timestamps. Fields must note ISO 8601 and UTC in their description.',
path: ['paths', '/resources', 'get', 'parameters', '1'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'test with requestBody properties',
document: {
paths: {
'/resources': {
post: {
requestBody: {
content: {
'application/json': {
schema: {
properties: {
scheduledFor: {
type: 'string',
format: 'date-time',
description: 'When to schedule the job using ISO 8601 format in UTC.',
},
expiresAt: {
type: 'string',
format: 'date-time',
description: 'When this resource expires.', // Missing ISO 8601 and UTC
},
},
},
},
},
},
},
},
},
},
errors: [
{
code: 'xgen-IPA-121-date-time-fields-mention-iso-8601',
message:
'API producers must use ISO 8601 date-time format in UTC for all timestamps. Fields must note ISO 8601 and UTC in their description.',
path: [
'paths',
'/resources',
'post',
'requestBody',
'content',
'application/json',
'schema',
'properties',
'expiresAt',
],
severity: DiagnosticSeverity.Warning,
},
],
},
]);
1 change: 1 addition & 0 deletions tools/spectral/ipa/ipa-spectral.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extends:
- ./rulesets/IPA-117.yaml
- ./rulesets/IPA-118.yaml
- ./rulesets/IPA-119.yaml
- ./rulesets/IPA-121.yaml
- ./rulesets/IPA-123.yaml
- ./rulesets/IPA-125.yaml

Expand Down
22 changes: 22 additions & 0 deletions tools/spectral/ipa/rulesets/IPA-121.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# IPA-121: Datetime
# http://go/ipa/121

functions:
- IPA121DateTimeFieldsMentionISO8601

rules:
xgen-IPA-121-date-time-fields-mention-iso-8601:
description: |
Fields with format="date-time" should mention ISO 8601 and UTC in their description.
It collects adoption metrics at schema property level and parameter level
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-121-date-time-fields-mention-iso-8601'
given:
- $.paths..parameters[*]
- $.components.parameters[*]
- $.components.schemas..properties[*]
- $.paths..requestBody..schema..properties[*]
- $.paths..responses..schema..properties[*]
resolved: false
severity: warn
then:
function: IPA121DateTimeFieldsMentionISO8601
12 changes: 12 additions & 0 deletions tools/spectral/ipa/rulesets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,18 @@ All cloudProviderEnumValues should be listed in the enum array.



### IPA-121

Rules are based on [http://go/ipa/IPA-121](http://go/ipa/IPA-121).

#### xgen-IPA-121-date-time-fields-mention-iso-8601

![warn](https://img.shields.io/badge/warning-yellow)
Fields with format="date-time" should mention ISO 8601 and UTC in their description.
It collects adoption metrics at schema property level and parameter level



### IPA-123

Rules are based on [http://go/ipa/IPA-123](http://go/ipa/IPA-123).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { hasException } from './utils/exceptions.js';
import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js';

const RULE_NAME = 'xgen-IPA-121-date-time-fields-mention-iso-8601';
const ERROR_MESSAGE =
'API producers must use ISO 8601 date-time format in UTC for all timestamps. Fields must note ISO 8601 and UTC in their description.';

export default (input, options, { path }) => {
const fieldType = path[path.length - 2];

if (hasException(input, RULE_NAME)) {
collectException(input, RULE_NAME, path);
return;
}

let format;
let description = input.description;
if (fieldType === 'parameters') {
format = input.schema?.format;
} else if (fieldType === 'properties') {
format = input.format;
}

if (format === 'date-time') {
if (!description?.includes('ISO 8601') && !description?.includes('UTC')) {
return collectAndReturnViolation(path, RULE_NAME, [
{
path,
message: ERROR_MESSAGE,
},
]);
}

collectAdoption(path, RULE_NAME);
}
};
Loading