- API Access Validator
- Config Validator
- YAML/OpenAPI Spec Validator
- File Access Validator
- Markdown Linter
- Markdown HTML Validator
- Release Notes Validator
- Download API Zip Generator
File: scripts/api-access-validator.js
Target File: config/api-access-definition.yaml
- ✅ Root element must be an array
- ✅ Array cannot be empty
Each entry in the array must satisfy:
- ✅ Entry must be an object - Cannot be null or non-object type
- ✅ Level field requirement - Must have exactly ONE of:
xChildProductName(Level 0)xGroupName(Level 1)xProxyName(Level 2)
- ❌ Cannot have more than one level field defined (multiple
xProxyName, etc.) - ❌ Cannot have zero level fields defined (must at least have
xProxyName)
xChildProductName (optional):
- ✅ Must be a non-empty string
- ✅ Must be trimmed (no whitespace-only strings)
- ✅ Can only be used at top level (level 0)
xGroupName (optional):
- ✅ Must be a non-empty string
- ✅ Must be trimmed (no whitespace-only strings)
- ✅ Can only be defined at level 1
xProxyName:
- ✅ Must be a non-empty string
- ✅ Must be trimmed (no whitespace-only strings)
- ✅ Can only be defined at level 2
- ✅
groupsfield must exist - ✅
groupsmust be an array - ✅ Each group must be a non-empty string
- ✅ Group names can only contain: alphanumeric characters, underscores (_), and hyphens (-)
- ❌ Invalid characters in group names will fail validation
- ✅ Must be an array
- ✅ Each version must be a non-empty string
- ✅ Must be an array
- ✅ Each section is validated recursively with the same rules
- ✅ Section must have one of:
xChildProductName,xGroupName, orxProxyName - ✅ Level constraints are enforced based on nesting depth
File: scripts/config-validator.js
Target Files:
config/document-explorer-definition.yamlconfig/recipe-explorer-definition.yaml(optional)config/product-layout.yamlconfig/tenant.json
File Pattern: (document|recipe)-explorer-definition.yaml
- ✅ Each section must have a
titlefield - ✅ If
linkis present withouttitle, error is reported with line number - ✅ Invalid section objects without title or link are flagged
- ✅ Link must have non-zero length
- ✅ Link must match
.mdor.mdxfile extension pattern - ✅ For local links (not containing "branch"):
- Link must exist in the repository filesystem
- Missing files are reported with line number
- ✅ For branch-based links:
- Validated against GitHub API
- 404 errors reported if file missing from GitHub repo
- Other HTTP errors are thrown as exceptions
- ✅ Subsections are validated recursively with same rules
File: config/product-layout.yaml
- ✅ Must be valid YAML
- ✅ Cannot contain improper
<br>tags (must use<br />) - ✅ Cannot contain
<\ br>or<\br>tags - ❌ Regex patterns checked:
/(\<br\s*\>)/giand/(\<\\\s?br\s*\>)/gi
- ✅ Must be valid JSON
- ✅ For non-"Support" tenants,
solutionfield must exist - ✅
solutionarray must contain only valid solutions:- For fiserv-resources (internal tenant):
["fiserv-resources"] - For others:
["merchants", "financial-institutions", "fintech", "carat"]
- For fiserv-resources (internal tenant):
- ❌ Invalid solutions in array will fail validation
- ✅ Product URLs starting with
/vmust include the product name (such as/v1/doctree/DeveloperStudioTest) - ✅ Ignored URLs: "developers", "merchants", "applications"
- ✅ Format check:
product.{urlKey}should containdata.name
- ✅ If
api-access-definition.yamlexists,product.accessConfigmust be defined - ❌ Missing
accessConfigwhen definition file exists will fail
- ✅
getStartedFilePathmust exist - ✅ Referenced file must exist in the docs directory
- ✅ Leading slash is handled automatically
- ✅ Referenced file must exist in the docs directory
- ✅
product.descriptionmust exist - ✅ Description length must be between 1 and 112 characters
- ❌ Empty or too-long descriptions will fail
- ✅ Each API version must have
versionandversionTypefields - ✅
releaseNotesPathmust be non-empty and match.mdor.mdxpattern - ✅ Each
apiSpecFileNamesentry must exist inreference/{version}/directory - ✅ Only ONE major version allowed
- ✅ Major version must be the highest version number
- ✅ Versions are sorted descendingly to verify major version
- ✅ Explorer definition file (document or recipe) must exist
- ✅ Product layout file must exist
- ✅ Tenant config file must exist
- ❌ Missing any required file will fail validation
File: scripts/validator-yaml.js
Target Files: reference/{version}/*.yaml (OpenAPI specs)
- ✅ All spec files listed in
tenant.jsonapiSpecFileNamesmust exist
- ✅
openapifield must be defined - ✅ Version must be between 3.0.0 and 3.0.3 (inclusive)
- ❌ Missing or out-of-range version fails validation
- ✅
pathsobject must exist - ✅
pathsmust contain at least one entry - ❌ Empty paths object fails validation
- ✅ Full OpenAPI schema validation using
@apidevtools/swagger-parser - ✅ Schema must pass SwaggerParser.validate()
For each path and method combination:
x-proxy-name:
- ✅ Must be present (required field)
- ✅ Must start with an alphabetical character (A-Z, a-z)
- ❌ Non-alphabetical first character fails validation
x-group-name:
- ✅ If present, must start with a word character (alphanumeric or underscore)
- ❌ Starting with non-word character fails validation
- ✅ Checks for duplicate APIs using composite key:
{path}_{method}_{version}_{x-core} - ❌ Duplicate APIs across files will fail with reference to both files
- ✅ Description fields in request body and responses are converted to HTML
- ✅ Uses Showdown converter with GitHub-compatible settings
File: scripts/file-access-validator.js
Target Files:
config/files-access-definition.yamlassets/files/*
- ✅
filePathfield must exist - ✅ Referenced file must exist in
assets/files/directory - ✅ File must use supported file type extension
- ✅ Supported file types:
doc,docxgzmdmsipdfpngppt,pptxtxtxls,xlsxzip
- ❌ Unsupported file types fail validation
- ❌ File names cannot contain spaces
- ❌ Missing files fail validation
- ✅
accessfield must exist - ✅ Access level must be one of:
"public"or"private" - ❌ Invalid or missing access level fails validation
- ✅ Private files must have
groupsfield defined - ✅ Group names can only contain alphanumeric characters, underscores, and hyphens
- ❌ Improper group names (containing other special characters) fail validation
- ❌ Missing groups for private files fail validation
File: scripts/md-linter.js
Target Files: docs/**/*.md and docs/**/*.mdx
Uses markdownlint library with custom configuration:
- ✅ All default markdownlint rules EXCEPT the following disabled ones
⚠️ no-hard-tabs- Hard tabs are allowed⚠️ whitespace- Trailing whitespace allowed⚠️ line_length- No line length limit⚠️ no-duplicate-heading- Duplicate headings allowed⚠️ first-line-heading- First line doesn't need to be heading⚠️ heading-style- Heading style not enforced⚠️ no-inline-html- Inline HTML allowed⚠️ no-bare-urls- Bare URLs allowed
- ✅ Files must have
.mdor.mdxextension - ❌ Invalid file extensions fail validation
- ✅ Recursively processes all subdirectories
File: scripts/md-validator.js
Target Files: docs/**/*.md, docs/**/*.mdx, recipes/**/*.md, recipes/**/*.mdx
GitHub Raw Links:
- ❌ Raw GitHub links not allowed:
raw.githubusercontent.com - ❌ GitHub file links not allowed:
github.com/Fiserv/.../raw/...or.../files/... - ✅ Images should use
/assets/imagesinstead - ✅ Files should use
/assetsinstead
Local Asset Links:
- ✅ Links matching
localhost:8080/api/(hosted-image|download)/are validated - ✅ Referenced asset files must exist in the repository
- ❌ Missing asset files fail validation
- ✅ All image
srcattributes are extracted and validated - ✅ Uses regex:
/<img.*?src=["'](.*?)["']/g
BR Tag Validation:
- ❌
<br>must be self-closing:<br /> - ❌ Improper formats flagged:
/(\<br\s*\>)/gi - ❌ Backslash variations flagged:
/(\<\\\s?br\s*\>)/gi - ✅ Reports line number and count of violations
Double Curly Braces:
- ❌
{{must be escaped as\{\{ - ✅ Reports line number of violations
Unclosed HTML Tags:
- ✅ Detects opening tags without corresponding closing tags
- ✅ Ignores tags within quotes (single, double, or backticks)
- ✅ Excludes
<br>tags from this check - ❌ Unclosed tags must either:
- Be escaped:
\<tagname> - Have closing tag:
</tagname>
- Be escaped:
- ✅ Reports tag name and line number
- ✅ Recursively processes
docs/andrecipes/directories - ❌ Invalid subdirectories or non-markdown files are flagged
- ✅
config.yamlfiles are ignored (allowed in docs)
File: scripts/release-notes-validator.js
Target Directory: docs/**/release*note*/
- ✅ Must have a directory matching pattern:
/release.*note/i - ❌ Missing release notes directory fails validation
- ✅ Release notes directory must contain at least one markdown file
- ✅ Searches recursively through subdirectories
- ✅ Valid markdown extensions:
.mdor.mdx - ❌ Empty release notes directory fails validation
File: scripts/download-api-zip.js
Target Files: reference/{version}/*.yaml
Output:
assets/{tenant}_spec.zipassets/{tenant}_postman.zip
- ✅ All checks from YAML Validator (Section 3) apply
- ✅ Spec files must exist
- ✅ Must be valid YAML
- ✅ Must pass SwaggerParser validation
- ✅
pathsobject must exist and be non-empty - ✅ Each API must have
x-proxy-name
- ✅ Adds valid spec files to
{tenant}_spec.zip - ✅ Maintains directory structure:
{repo}/{path}/{filename} - ✅ Handles both reference and references folders
- ✅ Writes zip to
assets/directory
- ✅ Converts OpenAPI specs to Postman collections using
openapi-to-postmanv2 - ✅ Times out after 5 seconds per conversion
- ✅ Adds generated collections to
{tenant}_postman.zip - ✅ JSON format with .json extension
- ✅ Maintains same directory structure as spec files
⚠️ Warnings for failed conversions (doesn't fail overall validation)
| Validator | Target Files | Key Validations | Critical Checks |
|---|---|---|---|
| API Access | api-access-definition.yaml |
Structure, levels, groups | Exactly one level per entry, valid group names |
| Config | tenant.json, explorer definitions, product layout |
Solutions, paths, versions | File existence, API versions, major version uniqueness |
| YAML/OpenAPI | reference/**/*.yaml |
OpenAPI schema, x-fields, duplicates | Version 3.0.x, x-proxy-name required, no duplicates |
| File Access | files-access-definition.yaml |
File types, access levels, groups | Supported extensions, no spaces, private files need groups |
| MD Linter | docs/**/*.md(x) |
Markdown syntax | Default markdownlint rules (with exceptions) |
| MD HTML | docs/**/*.md(x) |
Links, images, HTML tags | No GitHub raw links, closed tags, escaped special chars |
| Release Notes | docs/**/release*note*/ |
Directory and content | Must exist with at least one markdown file |
| ZIP Generator | reference/**/*.yaml |
Spec validity, Postman conversion | All OpenAPI checks, successful zip creation |
- Missing required files
- Invalid JSON/YAML syntax
- Schema validation failures
- Broken links to local files
- Missing required fields
- Invalid field values
- Improper HTML tags in markdown
- Duplicate API definitions
- Postman conversion failures
- GitHub API fetch errors (non-404)
- Missing optional fields
- Successful validations
- Skipped validations (file not found scenarios)
Last Updated: February 12, 2026