Skip to content

chore(docs): add markdownlint and fix all SDK page violations#306

Draft
marythought wants to merge 8 commits intomainfrom
chore/add-markdownlint
Draft

chore(docs): add markdownlint and fix all SDK page violations#306
marythought wants to merge 8 commits intomainfrom
chore/add-markdownlint

Conversation

@marythought
Copy link
Copy Markdown
Contributor

@marythought marythought commented Apr 23, 2026

Summary

  • Add .markdownlint.yaml config based on data-security-platform, tuned for Docusaurus MDX
  • Add CI workflow that lints changed .md/.mdx files on PRs
  • Fix all markdownlint violations across 13 SDK documentation pages (944 → 0 errors)

Changes by category

  • Duplicate h1: Removed # Heading from all pages (frontmatter title: renders as h1)
  • Emphasis as heading (MD036): Converted **Signature**, **Parameters**, **Returns**, **Example** to proper headings throughout
  • Collapsible sections: Converted <details>/<summary> method wrappers in policy.mdx and obligations.mdx to proper ### headings
  • Heading hierarchy: Restructured tdf.mdx with ## Manage TDFs parent, promoted experimental sub-headings
  • Fragment links (MD051): Moved Encrypt/Decrypt Options headings into tdf.mdx; fixed renamed anchors in policy.mdx and obligations.mdx
  • Table formatting (MD060): Ran prettier on all pages
  • Code block languages (MD040): Added text language to error output blocks in troubleshooting.mdx
  • HTML cards: Replaced Docusaurus HTML card layout in quickstart/index.mdx with markdown list
  • MDX components: Added all imported JSX components to MD033 allow list

Closes #305

Post-merge admin step

After merging, add "Markdownlint" as a required status check in Settings → Branches → Branch protection rules → main → Require status checks to pass before merging. The workflow only runs on PRs that touch markdown files, so it won't block unrelated PRs.

Test plan

  • npx markdownlint-cli2 "docs/sdks/**/*.mdx" passes with 0 errors
  • npx docusaurus build succeeds
  • Visual review of SDK pages on Surge preview — verify headings, tables, and navigation

🤖 Generated with Claude Code

marythought and others added 6 commits April 22, 2026 16:46
- Remove duplicate h1 (frontmatter title already renders as h1)
- Add MDX components to MD033 allow list in markdownlint config
- Move Encrypt/Decrypt Options headings into tdf.mdx to fix MD051 fragment links
- Convert bold emphasis to proper headings (MD036)
- Restructure heading hierarchy: add "Manage TDFs" h2, demote methods to h3
- Promote experimental section sub-headings to h3
- Run prettier to fix table column style (MD060)

Closes #305

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove duplicate h1
- Convert details/summary collapsibles to proper h3 headings
- Convert bold emphasis to h4 headings (Signature, Parameters, etc.)
- Add language to fenced code block (MD040)
- Fix fragment link for renamed heading
- Run prettier for table formatting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove duplicate h1
- Convert details/summary collapsibles to proper h3 headings
- Convert bold emphasis to h4 headings
- Fix fragment links for renamed headings
- Run prettier for table formatting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove duplicate h1
- Convert bold emphasis to h3 headings
- Run prettier for table formatting and blank lines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove duplicate h1
- Convert bold emphasis to h3 headings
- Run prettier for table formatting and blank lines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove duplicate h1 from all pages
- Replace HTML card layout with markdown list in quickstart index
- Convert bold emphasis to headings in authentication.mdx
- Add language to fenced code blocks in troubleshooting.mdx
- Fix blank line around fenced code block in list
- Run prettier for table formatting and blank lines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@marythought marythought requested review from a team as code owners April 23, 2026 00:24
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

Warning

Rate limit exceeded

@marythought has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 37 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 4 minutes and 37 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 38026219-9599-41d0-be9a-47184ccd48f1

📥 Commits

Reviewing files that changed from the base of the PR and between 043a381 and a3d5951.

📒 Files selected for processing (3)
  • .github/workflows/markdownlint.yaml
  • code_samples/tdf/decrypt_options.mdx
  • code_samples/tdf/encrypt_options.mdx
📝 Walkthrough

Walkthrough

Introduces .markdownlint.yaml configuration to enforce markdown formatting standards across SDK documentation. Updates 15+ documentation files to comply with linting rules: removes duplicate headings, standardizes code formatting with double quotes, converts bold section labels to proper markdown headings, and adjusts table alignment.

Changes

Cohort / File(s) Summary
Linting Configuration
.markdownlint.yaml
Introduces markdownlint configuration that disables line-length checks (MD013), permits MDX/frontmatter patterns (MD041), enforces table column styles (MD060), and allows specified inline HTML elements (MD033).
Core SDK Documentation
docs/sdks/authentication.mdx, docs/sdks/authorization.mdx, docs/sdks/discovery.mdx
Standardizes imports and code examples to double quotes with consistent multi-line formatting; converts bold section labels (**Signature**, **Parameters**, etc.) to ### headings; removes redundant in-page title heading; adjusts markdown table column alignment.
Advanced SDK Topics
docs/sdks/obligations.mdx, docs/sdks/policy.mdx
Replaces collapsible <details> sections with static ###/#### headings for operations/subsections; normalizes JS code formatting to double quotes; reformats parameter/return/example tables with adjusted column widths; updates internal link anchors.
SDK Reference & Utilities
docs/sdks/platform-client.mdx, docs/sdks/tdf.mdx, docs/sdks/troubleshooting.mdx
Standardizes double-quoted imports and code examples; removes duplicate top-level headings; restructures section hierarchy (e.g., ## CreateTDF## Manage TDFs with ### CreateTDF); adjusts table formatting and spacing; reformats code block indentation.
SDK Configuration Examples
code_samples/tdf/decrypt_options.mdx, code_samples/tdf/encrypt_options.mdx
Removes redundant "Decrypt Options" and "Encrypt Options" section headings; all option subsections remain unchanged.
Quickstart Guides
docs/sdks/index.mdx, docs/sdks/quickstart/index.mdx, docs/sdks/quickstart/go.mdx, docs/sdks/quickstart/java.mdx, docs/sdks/quickstart/javascript.mdx
Removes duplicate quickstart/SDK title headings; standardizes import quotes to double quotes; reformats code snippets with consistent multi-line imports and formatting; restructures "Choose Your SDK" section from grid to bullet list; adjusts spacing around code blocks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • elizabethhealy
  • jp-ayyappan
  • dmihalcik-virtru

Poem

🐰 ✨ Hops of consistency through markdown's way,
With double quotes dancing and headings at play,
No more bold confusion, just ### so clear,
Tables aligned perfect—linting brings cheer!
Markdown behaves now, from first hop to last. 📋

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding markdownlint configuration and fixing all related violations across SDK documentation pages.
Linked Issues check ✅ Passed All coding objectives from issue #305 are met: markdownlint configuration added with proper MDX/Docusaurus tuning, all violations fixed across SDK pages, and exceptions configured as specified.
Out of Scope Changes check ✅ Passed All changes are within scope of issue #305: linter config, violation fixes, and documentation reformatting to comply with linting rules.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/add-markdownlint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a .markdownlint.yaml configuration and performs extensive formatting updates across the SDK documentation to ensure consistency. Key changes include standardizing quote usage in code blocks, improving table alignment, and adjusting heading levels for better structure. One piece of feedback was provided regarding invalid JavaScript syntax in an object literal example within the policy documentation.

Comment thread docs/sdks/policy.mdx
// JavaScript
{ name: 'read' }
{
name: "read";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The semicolon inside this object literal is invalid JavaScript syntax. It should be removed to correctly represent a JavaScript object literal.

  name: "read"

@github-actions
Copy link
Copy Markdown
Contributor

📄 Preview deployed to https://opentdf-docs-pr-306.surge.sh

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
.markdownlint.yaml (1)

1-30: Consider setting an explicit style for MD060.

MD060 accepts values "aligned", "compact", "tight", and "any" (default). With MD060: true, the default "any" style is applied, which accepts any of the supported styles per table — lenient enough that it effectively won't catch much. Given the PR ran Prettier (which produces aligned tables), consider style: aligned to lock in the style chosen by this PR:

Optional tightening
-MD060: true # Table column style
+MD060:
+  style: aligned

Otherwise the config YAML parses correctly (comments on the mapping-key lines are ignored; the indented block becomes the value).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.markdownlint.yaml around lines 1 - 30, Replace the current boolean MD060:
true entry with an explicit mapping that sets the desired table style;
specifically update the MD060 rule (the MD060 key in the config) to use style:
aligned so markdownlint enforces aligned tables instead of the permissive
default "any".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/sdks/discovery.mdx`:
- Around line 807-812: The docs pass the platform root as defaultKASEndpoint,
which is wrong; update the example so defaultKASEndpoint points to the KAS
endpoint (e.g., `${platformUrl}/kas`) when constructing the OpenTDF client and
calling createTDF; locate the OpenTDF instantiation and the createTDF call
(symbols: OpenTDF, client, createTDF, defaultKASEndpoint) and change the value
to the platform KAS URL rather than platformUrl.

In `@docs/sdks/policy.mdx`:
- Around line 2412-2417: Replace the invalid object literal that uses a
semicolon after the property (the block showing { name: "read"; }) with valid
JavaScript syntax; either change the semicolon to nothing or a comma if adding
more properties, or assign the object to a constant like const action = { name:
"read" }; so the property name and value ("name": "read") are valid and the
example compiles.

In `@docs/sdks/quickstart/javascript.mdx`:
- Around line 264-277: After creating the missing marketing value with
platform.v1.attributes.createAttributeValue, the code still uses the original
stale attribute object (variable attribute) to derive attributeValueId which can
be undefined; fix this by reloading the attribute (e.g., call
platform.v1.attributes.getAttribute or re-run listAttributes and find the
attribute by name/namespace) after await
platform.v1.attributes.createAttributeValue resolves, then read attribute.values
to derive attributeValueId before calling the subject mapping code (the same
refresh is needed for the logic around attributeValueId at the later reference).

---

Nitpick comments:
In @.markdownlint.yaml:
- Around line 1-30: Replace the current boolean MD060: true entry with an
explicit mapping that sets the desired table style; specifically update the
MD060 rule (the MD060 key in the config) to use style: aligned so markdownlint
enforces aligned tables instead of the permissive default "any".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 33aaddf6-37bd-4e63-9870-059aae35c042

📥 Commits

Reviewing files that changed from the base of the PR and between 478c1a0 and 043a381.

📒 Files selected for processing (16)
  • .markdownlint.yaml
  • code_samples/tdf/decrypt_options.mdx
  • code_samples/tdf/encrypt_options.mdx
  • docs/sdks/authentication.mdx
  • docs/sdks/authorization.mdx
  • docs/sdks/discovery.mdx
  • docs/sdks/index.mdx
  • docs/sdks/obligations.mdx
  • docs/sdks/platform-client.mdx
  • docs/sdks/policy.mdx
  • docs/sdks/quickstart/go.mdx
  • docs/sdks/quickstart/index.mdx
  • docs/sdks/quickstart/java.mdx
  • docs/sdks/quickstart/javascript.mdx
  • docs/sdks/tdf.mdx
  • docs/sdks/troubleshooting.mdx
💤 Files with no reviewable changes (2)
  • code_samples/tdf/decrypt_options.mdx
  • code_samples/tdf/encrypt_options.mdx

Comment thread docs/sdks/discovery.mdx
Comment on lines 807 to 812
const client = new OpenTDF({ ...auth, platformUrl });
const ciphertext = await client.createTDF({
source: { type: 'stream', location: dataStream },
attributes: required,
defaultKASEndpoint: platformUrl,
source: { type: "stream", location: dataStream },
attributes: required,
defaultKASEndpoint: platformUrl,
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect defaultKASEndpoint examples and confirm platform-root usage is not copied elsewhere.
rg -n -C2 'defaultKASEndpoint:' --glob '*.mdx'

Repository: opentdf/docs

Length of output: 6483


Use the KAS endpoint, not the platform root.

Line 811 passes platformUrl as defaultKASEndpoint, but quickstart examples and other docs use ${platformUrl}/kas. This workflow will contact the wrong endpoint.

Proposed fix
 const ciphertext = await client.createTDF({
   source: { type: "stream", location: dataStream },
   attributes: required,
-  defaultKASEndpoint: platformUrl,
+  defaultKASEndpoint: `${platformUrl}/kas`,
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const client = new OpenTDF({ ...auth, platformUrl });
const ciphertext = await client.createTDF({
source: { type: 'stream', location: dataStream },
attributes: required,
defaultKASEndpoint: platformUrl,
source: { type: "stream", location: dataStream },
attributes: required,
defaultKASEndpoint: platformUrl,
});
const client = new OpenTDF({ ...auth, platformUrl });
const ciphertext = await client.createTDF({
source: { type: "stream", location: dataStream },
attributes: required,
defaultKASEndpoint: `${platformUrl}/kas`,
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/sdks/discovery.mdx` around lines 807 - 812, The docs pass the platform
root as defaultKASEndpoint, which is wrong; update the example so
defaultKASEndpoint points to the KAS endpoint (e.g., `${platformUrl}/kas`) when
constructing the OpenTDF client and calling createTDF; locate the OpenTDF
instantiation and the createTDF call (symbols: OpenTDF, client, createTDF,
defaultKASEndpoint) and change the value to the platform KAS URL rather than
platformUrl.

Comment thread docs/sdks/policy.mdx
Comment on lines 2412 to 2417
```typescript
// JavaScript
{ name: 'read' }
{
name: "read";
}
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find JavaScript/TypeScript docs snippets that show `name: "read";` as an object member.
rg -n -C2 'name:\s*"read";' --glob '*.mdx'

Repository: opentdf/docs

Length of output: 225


Fix the JavaScript object syntax at line 2415.

The semicolon after name: "read" is invalid in a JavaScript object literal; object properties should be comma-separated. Change to valid syntax.

Proposed fix
 ```typescript
 // JavaScript
-{
-  name: "read";
-}
+const action = { name: "read" };

</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/sdks/policy.mdx` around lines 2412 - 2417, Replace the invalid object
literal that uses a semicolon after the property (the block showing { name:
"read"; }) with valid JavaScript syntax; either change the semicolon to nothing
or a comma if adding more properties, or assign the object to a constant like
const action = { name: "read" }; so the property name and value ("name": "read")
are valid and the example compiles.

Comment on lines 264 to 277
// Ensure the marketing value exists on the attribute
const marketingFqn = `${deptFqn}/value/marketing`;
const listResp = await platform.v1.attributes.listAttributes({});
const attribute = listResp.attributes.find(
(attr) => attr.name === 'department' && attr.namespace?.id === namespaceId
(attr) => attr.name === "department" && attr.namespace?.id === namespaceId,
);

if (!(await attributeValueExists(platformUrl, auth, marketingFqn))) {
await platform.v1.attributes.createAttributeValue({
attributeId: attribute?.id,
value: 'marketing',
value: "marketing",
});
console.log('✅ Added marketing value to department attribute');
console.log("✅ Added marketing value to department attribute");
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Refresh the attribute before deriving attributeValueId.

When Line 271 creates the missing marketing value, Line 321 still reads from the pre-create attribute.values, so attributeValueId can be undefined and the subject mapping call will fail.

Proposed fix
 // Get the attribute value ID for "marketing"
-const marketingValue = attribute?.values?.find((v) => v.value === "marketing");
-const attributeValueId = marketingValue?.id;
+const refreshedAttributes = await platform.v1.attributes.listAttributes({});
+const refreshedAttribute = refreshedAttributes.attributes.find(
+  (attr) => attr.name === "department" && attr.namespace?.id === namespaceId,
+);
+const marketingValue = refreshedAttribute?.values?.find(
+  (v) => v.value === "marketing",
+);
+if (!marketingValue?.id) {
+  throw new Error("Marketing value not found in department attribute");
+}
+const attributeValueId = marketingValue.id;

Also applies to: 320-322

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/sdks/quickstart/javascript.mdx` around lines 264 - 277, After creating
the missing marketing value with platform.v1.attributes.createAttributeValue,
the code still uses the original stale attribute object (variable attribute) to
derive attributeValueId which can be undefined; fix this by reloading the
attribute (e.g., call platform.v1.attributes.getAttribute or re-run
listAttributes and find the attribute by name/namespace) after await
platform.v1.attributes.createAttributeValue resolves, then read attribute.values
to derive attributeValueId before calling the subject mapping code (the same
refresh is needed for the logic around attributeValueId at the later reference).

marythought and others added 2 commits April 22, 2026 18:10
Runs on PRs that touch .md/.mdx files. Only lints changed files,
not the entire repo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove trailing blank line in decrypt_options.mdx (MD012)
- Use absolute link for cross-file fragment in encrypt_options.mdx (MD051)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@marythought marythought marked this pull request as draft April 23, 2026 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(docs): add markdownlint to CI

1 participant