From e505b7585ca44397eb35cfd7cbec157c06afd257 Mon Sep 17 00:00:00 2001 From: James Bush <37296643+bushjames@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:45:49 +0100 Subject: [PATCH 1/5] [feat] add responsible use of AI policy (#556) * [feat] add responsible use of AI policy * Update docs/community/standards/ai_policy.md Co-authored-by: Sam <10507686+elnyry-sam-k@users.noreply.github.com> * Update docs/community/standards/ai_policy.md Co-authored-by: Sam <10507686+elnyry-sam-k@users.noreply.github.com> --------- Co-authored-by: Sam <10507686+elnyry-sam-k@users.noreply.github.com> --- docs/.vuepress/config.js | 1 + .../contributing/contributors-guide.md | 10 +- docs/community/standards/ai_policy.md | 163 ++++++++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 docs/community/standards/ai_policy.md diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 71e0199b4..e2ceb4fe7 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -206,6 +206,7 @@ module.exports = { ['standards/versioning', 'Versioning'], ['standards/creating-new-features', 'Creating New Features'], ['standards/triaging-bugs', 'Triaging Bugs'], + ['standards/ai_policy', "AI Policy"], ] }, { diff --git a/docs/community/contributing/contributors-guide.md b/docs/community/contributing/contributors-guide.md index 9e5dfc416..06a839db3 100644 --- a/docs/community/contributing/contributors-guide.md +++ b/docs/community/contributing/contributors-guide.md @@ -2,6 +2,9 @@ We are glad that you are considering becoming a part of the Mojaloop community. +_Note: If you use or are planning to use Artificial Intelligence (AI) tools as part of your Mojaloop contribution workflow, +please ensure you have fully read and comply with our [responsible use of AI policy](../standards/ai_policy.md)._ + Based on the current phase of the Mojaloop project, we are looking for the following types of contributors: ## Types of contributors @@ -83,4 +86,9 @@ a production mobile money provider. ## Where do I send bugs, questions, and feedback? -For bugs, see [Reporting bugs](https://github.com/mojaloop/mojaloop/blob/master/contribute/Reporting-Bugs.md). \ No newline at end of file +For bugs, see [Reporting bugs](https://github.com/mojaloop/mojaloop/blob/master/contribute/Reporting-Bugs.md). + +## Policy on the Use of Artificial Intelligence (AI) Tools by Community Members + +If you use or are planning to use Artificial Intelligence (AI) tools as part of your Mojaloop contribution workflow, +please ensure you have fully read and comply with our [responsible use of AI policy](../standards/ai_policy.md). \ No newline at end of file diff --git a/docs/community/standards/ai_policy.md b/docs/community/standards/ai_policy.md new file mode 100644 index 000000000..344575b06 --- /dev/null +++ b/docs/community/standards/ai_policy.md @@ -0,0 +1,163 @@ +# Policy on the Responsible Use of Artificial Intelligence (AI) Tools by Community Members + +- Version: 1.0 +- Effective Date: 2026-04-08 +- Author: James Bush (jbush@mojaloop.io) +- Applies To: All contributors, maintainers, adopters, and participants in the Mojaloop community and its associated projects, including repositories under the Mojaloop GitHub organisation. + +**AI Disclosure** This document includes content generated with assistance from ChatGPT 5.2. All content has been reviewed and validated by the author. + +--- + +## 1. Purpose + +This policy establishes clear and pragmatic guidelines for the responsible use of Artificial Intelligence (AI) tools within the Mojaloop community. + +The Mojaloop Foundation supports innovation and productivity enhancements, including the use of AI-assisted tools. However, transparency, accountability, and community trust remain paramount. This policy ensures that AI use enhances collaboration without undermining openness, authorship integrity, or technical quality. + +--- + +## 2. Guiding Principles + +All AI use within the Mojaloop community must adhere to the following principles: + +1. **Human Accountability** – A human contributor is always responsible for the final output. +2. **Transparency** – Use of AI-generated content must be clearly disclosed. +3. **Quality and Security** – AI-generated outputs must meet Mojaloop’s engineering and documentation standards. +4. **Community Integrity** – AI must not be used in ways that disrupt or overwhelm community processes. + +--- + +## 3. Permitted Uses of AI Tools + +### 3.1 AI as Note-Takers in Community Calls + +AI tools may be used to take notes during **public Mojaloop community calls**, subject to the following conditions: + +- The AI tool user **must be personally present** in the call unless prior authorisation is obtained from the meeting host. +- AI note-taking tools may not join calls independently of a human participant without explicit prior authorisation from the meeting host. +- Anonymous AI bots are not permitted. All AI bots must disclose publicly the human community member they represent. +- AI note-taking tools may only join calls where call recording is enabled. + +**Rationale:** +The Mojaloop community values open discussion and psychological safety. The presence of numerous unattended recording or summarisation bots may discourage participation and negatively affect collaboration. + +--- + +### 3.2 AI Assistance in Documentation + +Community members may use AI tools to assist with: + +- Drafting documentation +- Improving clarity or grammar +- Reformatting content +- Generating summaries +- Translating content + +However: + +- Any document in which AI has generated **any portion of the content** must contain a clear statement in the document header specifying: + - That AI tools were used + - Which AI tool(s) were used + +**Example Disclosure Statement:** + + _This document includes content generated with assistance from [Tool Name]. All content has been reviewed and validated by the author._ + +Failure to disclose AI-assisted generation may result in the document being rejected or returned for correction. + +**Rationale:** +Transparency maintains trust in authorship and allows readers to assess provenance appropriately. + +--- + +### 3.3 AI Assistance in Code Creation and Debugging + +AI tools may be used for: + +- Code generation +- Code suggestions +- Refactoring assistance +- Debugging support +- Test generation +- Documentation generation for code + +However, the following rules strictly apply: + +#### 3.3.1 Human Submission Requirement + +- All pull requests (PRs), issues, and code submissions must be made by human contributors. +- Fully automated AI agents may not submit PRs, bug fixes, or code changes. +- All pull requests (PRs), issues, and code submissions must follow the Mojaloop community product engineering process requirements. +- The only exception is officially supported automated tools already integrated into GitHub workflows (e.g., dependency update bots such as Dependabot). + +Any automated agent submissions beyond approved GitHub-native tools will be **dismissed without review**. + +--- + +#### 3.3.2 Mandatory Human Review + +All AI-assisted code: + +- MUST be thoroughly reviewed by the human submitter. +- MUST be understood in full by the submitter. +- MUST meet Mojaloop coding standards and architectural principles. +- MUST pass all automated tests and validation pipelines. + +Code that is clearly AI-generated and has not been properly reviewed, validated, and understood by the human author will not be accepted into the codebase. + +The human contributor submitting the PR retains full accountability for: + +- Correctness +- Security +- Licensing compliance +- Architectural consistency +- Long-term maintainability + +**Rationale:** +Mojaloop operates in the financial services domain. The integrity, security, and correctness of code are non-negotiable. + +--- + +## 4. Prohibited Uses + +The following uses of AI are not permitted within Mojaloop community processes: + +- Unattended AI bots joining community calls. +- Fully autonomous AI agents submitting PRs or issues. +- Submitting AI-generated content without required disclosure (where applicable). +- Delegating architectural or design decisions to AI tools. +- Using AI tools to scrape, summarise, or redistribute restricted or confidential information without permission. + +--- + +## 5. Enforcement + +Maintainers and reviewers may: + +- Request disclosure statements be added. +- Reject PRs that appear insufficiently reviewed. +- Close automated agent submissions without comment. +- Request clarification regarding AI involvement. + +Repeated or deliberate violations may be escalated in accordance with Mojaloop community governance procedures. + +--- + +## 6. Future Review + +AI capabilities evolve rapidly. This policy will be reviewed periodically by the Mojaloop Foundation and community maintainers to ensure it remains appropriate, practical, and aligned with community values. + +--- + +## 7. Summary + +AI tools are permitted within the Mojaloop community when used responsibly and transparently. + +- Humans must remain accountable. +- AI must not overwhelm community processes. +- Disclosure is required in documentation. +- Code must always be reviewed and submitted by a human. + +The Mojaloop Foundation encourages thoughtful adoption of AI tools in ways that strengthen, not dilute, the quality, trust, and collaborative spirit of the Mojaloop ecosystem. + From b60581525f49815377f83ad73d66edfb4a0fef58 Mon Sep 17 00:00:00 2001 From: maximen Date: Sun, 12 Apr 2026 22:39:25 +0200 Subject: [PATCH 2/5] feat: add i18n drift check script and GitHub workflow - Introduced a new script `i18n-drift-check.mjs` to detect translation drift in documentation. - Added a GitHub Actions workflow to automate i18n drift reporting on pull requests and pushes to main. - Updated `package.json` to include a new script for running the i18n check and updated dependencies. --- .github/workflows/i18n-translation-drift.yml | 139 +++++++++++ package.json | 5 +- scripts/i18n-drift-check.mjs | 232 +++++++++++++++++++ 3 files changed, 374 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/i18n-translation-drift.yml create mode 100644 scripts/i18n-drift-check.mjs diff --git a/.github/workflows/i18n-translation-drift.yml b/.github/workflows/i18n-translation-drift.yml new file mode 100644 index 000000000..3938f15cc --- /dev/null +++ b/.github/workflows/i18n-translation-drift.yml @@ -0,0 +1,139 @@ +name: i18n translation drift + +on: + pull_request: + paths: + - "docs/**/*.md" + - "docs/.vuepress/config.js" + - "scripts/i18n-drift-check.mjs" + push: + branches: + - main + paths: + - "docs/**/*.md" + - "docs/.vuepress/config.js" + - "scripts/i18n-drift-check.mjs" + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + report-pr: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Generate i18n drift report + run: | + node scripts/i18n-drift-check.mjs \ + --base "${{ github.event.pull_request.base.sha }}" \ + --head "${{ github.event.pull_request.head.sha }}" \ + --json-out i18n-report.json \ + --markdown-out i18n-report.md + + - name: Upsert pull request comment + uses: actions/github-script@v7 + with: + script: | + const fs = require("fs"); + const body = fs.readFileSync("i18n-report.md", "utf8"); + const marker = ""; + const finalBody = `${marker}\n${body}`; + + const { owner, repo } = context.repo; + const issue_number = context.issue.number; + + const comments = await github.paginate(github.rest.issues.listComments, { + owner, + repo, + issue_number, + per_page: 100, + }); + + const existing = comments.find((comment) => + comment.user?.type === "Bot" && comment.body?.includes(marker) + ); + + if (existing) { + await github.rest.issues.updateComment({ + owner, + repo, + comment_id: existing.id, + body: finalBody, + }); + } else { + await github.rest.issues.createComment({ + owner, + repo, + issue_number, + body: finalBody, + }); + } + + - name: Upload i18n report artifact + uses: actions/upload-artifact@v4 + with: + name: i18n-report-pr + path: | + i18n-report.json + i18n-report.md + + create-issue-on-main: + if: github.event_name == 'push' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Generate i18n drift report + run: | + node scripts/i18n-drift-check.mjs \ + --base "${{ github.event.before }}" \ + --head "${{ github.sha }}" \ + --json-out i18n-report.json \ + --markdown-out i18n-report.md + + - name: Create issue when drift exists + uses: actions/github-script@v7 + with: + script: | + const fs = require("fs"); + const report = JSON.parse(fs.readFileSync("i18n-report.json", "utf8")); + const md = fs.readFileSync("i18n-report.md", "utf8"); + + if (!report.hasDrift) { + core.info("No translation drift detected; no issue created."); + return; + } + + const title = `i18n: translation updates required for ${context.sha.slice(0, 7)}`; + const body = [ + "This issue was auto-created after source documentation changes were merged to `main`.", + "", + md, + "", + "Please coordinate locale updates with maintainers/reviewers.", + ].join("\n"); + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title, + body, + }); + + - name: Upload i18n report artifact + uses: actions/upload-artifact@v4 + with: + name: i18n-report-main + path: | + i18n-report.json + i18n-report.md diff --git a/package.json b/package.json index 1c44f98d7..6e0e188f7 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "scripts": { "dev": "NODE_OPTIONS=--openssl-legacy-provider npx npx vuepress dev docs", "build": "NODE_OPTIONS='--max-old-space-size=8192' npx npx vuepress build docs", + "i18n:check": "node scripts/i18n-drift-check.mjs --base origin/main --head HEAD --markdown-out i18n-report.md --json-out i18n-report.json", "build:plantuml:all": "./scripts/_build_plantuml.sh", "build:plantuml:diff": "MODE=STAGED_GIT ./scripts/_build_plantuml.sh", "lint": "npx markdownlint './docs/**/*.md' --ignore node_modules --config markdownlint.yaml", @@ -24,10 +25,10 @@ "devDependencies": { "@vuepress/plugin-back-to-top": "^1.9.10", "@vuepress/plugin-medium-zoom": "^1.9.10", - "got": "^15.0.0", + "got": "^15.0.1", "husky": "^9.1.7", "markdownlint-cli": "^0.48.0", - "npm-check-updates": "^20.0.0", + "npm-check-updates": "^20.0.1", "plantuml-encoder": "^1.4.0", "svgo": "^4.0.1", "vuepress": "^1.9.10", diff --git a/scripts/i18n-drift-check.mjs b/scripts/i18n-drift-check.mjs new file mode 100644 index 000000000..c074a220f --- /dev/null +++ b/scripts/i18n-drift-check.mjs @@ -0,0 +1,232 @@ +#!/usr/bin/env node + +import fs from "node:fs"; +import path from "node:path"; +import process from "node:process"; +import { execSync } from "node:child_process"; + +function parseArgs(argv) { + const args = {}; + for (let i = 0; i < argv.length; i += 1) { + const current = argv[i]; + if (current.startsWith("--")) { + const key = current.slice(2); + const value = argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[i + 1] : "true"; + args[key] = value; + if (value !== "true") i += 1; + } + } + return args; +} + +function readLocalesFromVuepressConfig(configPath) { + const content = fs.readFileSync(configPath, "utf8"); + const lastLocalesIndex = content.lastIndexOf("locales:"); + if (lastLocalesIndex === -1) return []; + + const objectStart = content.indexOf("{", lastLocalesIndex); + if (objectStart === -1) return []; + + let depth = 0; + let objectEnd = -1; + for (let i = objectStart; i < content.length; i += 1) { + const char = content[i]; + if (char === "{") depth += 1; + if (char === "}") depth -= 1; + if (depth === 0) { + objectEnd = i; + break; + } + } + + if (objectEnd === -1) return []; + + const localesBlock = content.slice(objectStart, objectEnd + 1); + const matches = [...localesBlock.matchAll(/["']\/([a-zA-Z0-9_-]+)\/["']\s*:/g)]; + const locales = [...new Set(matches.map((m) => m[1]).filter((value) => value && value !== "/"))]; + return locales.sort(); +} + +function runGit(command) { + return execSync(command, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim(); +} + +function refExists(ref) { + if (!ref) return false; + try { + runGit(`git rev-parse --verify --quiet ${ref}^{commit}`); + return true; + } catch { + return false; + } +} + +function resolveBaseRef(requestedBase) { + const candidates = [ + requestedBase, + requestedBase?.startsWith("origin/") ? requestedBase.replace(/^origin\//, "") : null, + "origin/main", + "main", + "origin/master", + "master", + "HEAD~1", + "HEAD", + ].filter(Boolean); + + for (const candidate of candidates) { + if (refExists(candidate)) { + return candidate; + } + } + + return "HEAD"; +} + +function runGitDiff(baseRef, headRef) { + const command = `git diff --name-only ${baseRef}...${headRef}`; + const output = runGit(command); + return output + .split("\n") + .map((line) => line.trim()) + .filter(Boolean); +} + +function normalizePath(filePath) { + return filePath.split(path.sep).join("/"); +} + +function isSourceDoc(filePath, localeRoots) { + if (!filePath.startsWith("docs/")) return false; + if (!filePath.endsWith(".md")) return false; + if (filePath.startsWith("docs/.vuepress/")) return false; + return !localeRoots.some((locale) => filePath.startsWith(`docs/${locale}/`)); +} + +function toLocalizedPath(sourceFile, locale) { + const relativePath = sourceFile.slice("docs/".length); + return `docs/${locale}/${relativePath}`; +} + +function buildReport({ changedFiles, locales, repoRoot }) { + const changedSet = new Set(changedFiles.map(normalizePath)); + const sourceFiles = changedFiles.filter((file) => isSourceDoc(file, locales)); + + const impacted = sourceFiles.map((sourceFile) => { + const localeStatuses = locales.map((locale) => { + const localizedPath = toLocalizedPath(sourceFile, locale); + const absoluteLocalizedPath = path.join(repoRoot, localizedPath); + const exists = fs.existsSync(absoluteLocalizedPath); + + if (!exists) { + return { locale, path: localizedPath, status: "missing" }; + } + + if (!changedSet.has(localizedPath)) { + return { locale, path: localizedPath, status: "needs_review" }; + } + + return { locale, path: localizedPath, status: "updated" }; + }); + + return { source: sourceFile, locales: localeStatuses }; + }); + + const counts = { missing: 0, needs_review: 0, updated: 0 }; + for (const item of impacted) { + for (const localeInfo of item.locales) { + counts[localeInfo.status] += 1; + } + } + + return { + generatedAt: new Date().toISOString(), + changedFiles, + changedSourceFiles: sourceFiles, + locales, + impacted, + counts, + hasDrift: counts.missing > 0 || counts.needs_review > 0, + }; +} + +function buildMarkdownReport(report) { + if (report.changedSourceFiles.length === 0) { + return [ + "## Translation Drift Report", + "", + "No source markdown files changed in this diff range.", + ].join("\n"); + } + + const lines = [ + "## Translation Drift Report", + "", + `Detected locales: ${report.locales.map((locale) => `\`${locale}\``).join(", ") || "_none_"}`, + "", + `Source files changed: ${report.changedSourceFiles.length}`, + `- missing: ${report.counts.missing}`, + `- needs_review: ${report.counts.needs_review}`, + `- updated: ${report.counts.updated}`, + "", + ]; + + for (const item of report.impacted) { + lines.push(`### \`${item.source}\``); + for (const localeInfo of item.locales) { + const emoji = + localeInfo.status === "missing" + ? "❌" + : localeInfo.status === "needs_review" + ? "⚠️" + : "✅"; + lines.push(`- ${emoji} \`${localeInfo.locale}\`: \`${localeInfo.path}\` (${localeInfo.status})`); + } + lines.push(""); + } + + lines.push( + "> `needs_review` means translation exists but was not updated in the same diff range. Human review still required." + ); + + return lines.join("\n"); +} + +function main() { + const args = parseArgs(process.argv.slice(2)); + const repoRoot = process.cwd(); + const configPath = path.join(repoRoot, "docs/.vuepress/config.js"); + + const requestedBaseRef = args.base || "origin/main"; + const headRef = args.head || "HEAD"; + const jsonOut = args["json-out"]; + const markdownOut = args["markdown-out"]; + const failOnMissing = args["fail-on-missing"] === "true"; + const baseRef = resolveBaseRef(requestedBaseRef); + + if (baseRef !== requestedBaseRef) { + process.stderr.write( + `[i18n-check] Base ref "${requestedBaseRef}" not found. Falling back to "${baseRef}".\n` + ); + } + + const locales = readLocalesFromVuepressConfig(configPath); + const changedFiles = runGitDiff(baseRef, headRef); + const report = buildReport({ changedFiles, locales, repoRoot }); + const markdown = buildMarkdownReport(report); + + if (jsonOut) { + fs.writeFileSync(jsonOut, `${JSON.stringify(report, null, 2)}\n`, "utf8"); + } + + if (markdownOut) { + fs.writeFileSync(markdownOut, `${markdown}\n`, "utf8"); + } + + process.stdout.write(`${markdown}\n`); + + if (failOnMissing && report.counts.missing > 0) { + process.exit(2); + } +} + +main(); From 12af9a0b34022c5077ab9b4502fe81818ac2e280 Mon Sep 17 00:00:00 2001 From: maximen Date: Sun, 12 Apr 2026 22:45:31 +0200 Subject: [PATCH 3/5] fix: update i18n drift check script and GitHub workflow to use 'master' branch --- .github/workflows/i18n-translation-drift.yml | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/i18n-translation-drift.yml b/.github/workflows/i18n-translation-drift.yml index 3938f15cc..d7ade58aa 100644 --- a/.github/workflows/i18n-translation-drift.yml +++ b/.github/workflows/i18n-translation-drift.yml @@ -8,7 +8,7 @@ on: - "scripts/i18n-drift-check.mjs" push: branches: - - main + - master paths: - "docs/**/*.md" - "docs/.vuepress/config.js" @@ -84,7 +84,7 @@ jobs: i18n-report.json i18n-report.md - create-issue-on-main: + create-issue-on-master: if: github.event_name == 'push' runs-on: ubuntu-latest steps: @@ -116,7 +116,7 @@ jobs: const title = `i18n: translation updates required for ${context.sha.slice(0, 7)}`; const body = [ - "This issue was auto-created after source documentation changes were merged to `main`.", + "This issue was auto-created after source documentation changes were merged to `master`.", "", md, "", @@ -133,7 +133,7 @@ jobs: - name: Upload i18n report artifact uses: actions/upload-artifact@v4 with: - name: i18n-report-main + name: i18n-report-master path: | i18n-report.json i18n-report.md diff --git a/package.json b/package.json index 6e0e188f7..a27db281f 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "scripts": { "dev": "NODE_OPTIONS=--openssl-legacy-provider npx npx vuepress dev docs", "build": "NODE_OPTIONS='--max-old-space-size=8192' npx npx vuepress build docs", - "i18n:check": "node scripts/i18n-drift-check.mjs --base origin/main --head HEAD --markdown-out i18n-report.md --json-out i18n-report.json", + "i18n:check": "node scripts/i18n-drift-check.mjs --base origin/master --head HEAD --markdown-out i18n-report.md --json-out i18n-report.json", "build:plantuml:all": "./scripts/_build_plantuml.sh", "build:plantuml:diff": "MODE=STAGED_GIT ./scripts/_build_plantuml.sh", "lint": "npx markdownlint './docs/**/*.md' --ignore node_modules --config markdownlint.yaml", From 33d309b2fe51707404fc8c7d933ecaf9de26afe0 Mon Sep 17 00:00:00 2001 From: Sam <10507686+elnyry-sam-k@users.noreply.github.com> Date: Mon, 13 Apr 2026 15:17:46 +0530 Subject: [PATCH 4/5] chore: check infra lock and clear as needed (#559) --- .circleci/config.yml | 9 ++ package-lock.json | 315 ++++++++++++++++++++----------------------- package.json | 10 +- 3 files changed, 159 insertions(+), 175 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c7bd1bd91..30f026dcf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -144,6 +144,15 @@ jobs: rm terraform_${TERRAFORM_VERSION}_linux_amd64.zip environment: TERRAFORM_VERSION: 1.11.4 + - run: + name: Clear stale state lock (if present) + command: | + cd ./infra/src + terraform init \ + -backend-config="bucket=docs.mojaloop.io-state" \ + -backend-config="region=eu-west-2" \ + -backend-config="dynamodb_table=docs.mojaloop.io-lock" + terraform force-unlock -force 7232e661-3027-02c3-49da-f8cd72eefc89 || true - run: name: Update infrastructure command: | diff --git a/package-lock.json b/package-lock.json index a60b5e42c..d62e2ffd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,16 +11,16 @@ "devDependencies": { "@vuepress/plugin-back-to-top": "^1.9.10", "@vuepress/plugin-medium-zoom": "^1.9.10", - "got": "^14.6.5", + "got": "^15.0.1", "husky": "^9.1.7", - "markdownlint-cli": "^0.47.0", - "npm-check-updates": "^19.2.0", + "markdownlint-cli": "^0.48.0", + "npm-check-updates": "^20.0.1", "plantuml-encoder": "^1.4.0", - "svgo": "^4.0.0", + "svgo": "^4.0.1", "vuepress": "^1.9.10", "vuepress-plugin-mermaidjs": "^2.0.0-beta.2", "vuepress-plugin-versioning": "git+https://github.com/mojaloop/vuepress-plugin-versioning.git#dcb14962a69b8e5aaf184d2d1a31ae4f43870bc1", - "vuepress-theme-titanium": "^4.11.2" + "vuepress-theme-titanium": "^5.0.0" } }, "node_modules/@ampproject/remapping": { @@ -1778,29 +1778,6 @@ "deprecated": "Potential XSS vulnerability patched in v6.0.0.", "dev": true }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, - "engines": { - "node": "20 || >=22" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -1853,8 +1830,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@mrmlnc/readdir-enhanced": { "version": "2.2.1", @@ -1884,15 +1860,13 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@sindresorhus/is": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.0.1.tgz", - "integrity": "sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -1900,19 +1874,6 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.1" - }, - "engines": { - "node": ">=14.16" - } - }, "node_modules/@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -1993,11 +1954,10 @@ "dev": true }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true, - "license": "MIT" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "dev": true }, "node_modules/@types/http-proxy": { "version": "1.17.11", @@ -3920,6 +3880,27 @@ "node": ">=8" } }, + "node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/brace-expansion/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -4320,40 +4301,23 @@ } }, "node_modules/cacheable-request": { - "version": "13.0.12", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-13.0.12.tgz", - "integrity": "sha512-qqK/etGeI/9DV5yRkO50ApDTjip9UXPml1NHYJksUAw15yMLOf8VUO1/8bu4P8birOCqR+hYQ/nh1Lezc8sZrA==", + "version": "13.0.18", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-13.0.18.tgz", + "integrity": "sha512-rFWadDRKJs3s2eYdXlGggnBZKG7MTblkFBB0YllFds+UYnfogDp2wcR6JN97FhRkHTvq59n2vhNoHNZn29dh/Q==", "dev": true, - "license": "MIT", "dependencies": { "@types/http-cache-semantics": "^4.0.4", "get-stream": "^9.0.1", "http-cache-semantics": "^4.2.0", - "keyv": "^5.5.3", + "keyv": "^5.5.5", "mimic-response": "^4.0.0", - "normalize-url": "^8.1.0", - "responselike": "^3.0.0" + "normalize-url": "^8.1.1", + "responselike": "^4.0.2" }, "engines": { "node": ">=18" } }, - "node_modules/cacheable-request/node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", - "dev": true, - "license": "MIT", - "dependencies": { - "lowercase-keys": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -4807,6 +4771,18 @@ "node": ">=6.0" } }, + "node_modules/chunk-data": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chunk-data/-/chunk-data-0.1.0.tgz", + "integrity": "sha512-zFyPtyC0SZ6Zu79b9sOYtXZcgrsXe0RpePrzRyj52hYVFG1+Rk6rBqjjOEk+GNQwc3PIX+86teQMok970pod1g==", + "dev": true, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ci-info": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", @@ -5192,11 +5168,10 @@ } }, "node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", "dev": true, - "license": "MIT", "engines": { "node": ">=20" } @@ -7226,16 +7201,6 @@ "node": ">=6" } }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -9446,7 +9411,6 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "dev": true, - "license": "MIT", "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" @@ -9463,7 +9427,6 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -9672,49 +9635,41 @@ } }, "node_modules/got": { - "version": "14.6.5", - "resolved": "https://registry.npmjs.org/got/-/got-14.6.5.tgz", - "integrity": "sha512-Su87c0NNeg97de1sO02gy9I8EmE7DCJ1gzcFLcgGpYeq2PnLg4xz73MWrp6HjqbSsjb6Glf4UBDW6JNyZA6uSg==", + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/got/-/got-15.0.1.tgz", + "integrity": "sha512-InYCBboAj9YmFiMcxbIRQ/WPoLsKSc9t9EGaUjGENtxunnx8USWtRY/SO/V3VsHLfDvUxAO2Qmx+6fQyG1jjaw==", "dev": true, - "license": "MIT", "dependencies": { - "@sindresorhus/is": "^7.0.1", - "@szmarczak/http-timer": "^5.0.1", + "@sindresorhus/is": "^7.2.0", "byte-counter": "^0.1.0", "cacheable-lookup": "^7.0.0", - "cacheable-request": "^13.0.12", + "cacheable-request": "^13.0.18", + "chunk-data": "^0.1.0", "decompress-response": "^10.0.0", - "form-data-encoder": "^4.0.2", "http2-wrapper": "^2.2.1", - "keyv": "^5.5.3", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^4.0.1", + "keyv": "^5.6.0", + "lowercase-keys": "^4.0.1", "responselike": "^4.0.2", - "type-fest": "^4.26.1" + "type-fest": "^5.4.4", + "uint8array-extras": "^1.5.0" }, "engines": { - "node": ">=20" + "node": ">=22" }, "funding": { "url": "https://github.com/sindresorhus/got?sponsor=1" } }, - "node_modules/got/node_modules/form-data-encoder": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-4.0.2.tgz", - "integrity": "sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==", - "dev": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/got/node_modules/p-cancelable": { + "node_modules/got/node_modules/lowercase-keys": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-4.0.1.tgz", - "integrity": "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-4.0.1.tgz", + "integrity": "sha512-wI9Nui/L8VfADa/cr/7NQruaASk1k23/Uh1khQ02BCVYiiy8F4AhOGnQzJy3Fl/c44GnYSbZHv8g7EcG3kJ1Qg==", "dev": true, "engines": { - "node": ">=14.16" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/graceful-fs": { @@ -11427,11 +11382,10 @@ } }, "node_modules/keyv": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.3.tgz", - "integrity": "sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, - "license": "MIT", "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -11677,11 +11631,10 @@ } }, "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -11792,23 +11745,22 @@ } }, "node_modules/markdownlint-cli": { - "version": "0.47.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.47.0.tgz", - "integrity": "sha512-HOcxeKFAdDoldvoYDofd85vI8LgNWy8vmYpCwnlLV46PJcodmGzD7COSSBlhHwsfT4o9KrAStGodImVBus31Bg==", + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.48.0.tgz", + "integrity": "sha512-NkZQNu2E0Q5qLEEHwWj674eYISTLD4jMHkBzDobujXd1kv+yCxi8jOaD/rZoQNW1FBBMMGQpuW5So8B51N/e0A==", "dev": true, - "license": "MIT", "dependencies": { - "commander": "~14.0.2", + "commander": "~14.0.3", "deep-extend": "~0.6.0", "ignore": "~7.0.5", "js-yaml": "~4.1.1", "jsonc-parser": "~3.3.1", "jsonpointer": "~5.0.1", - "markdown-it": "~14.1.0", + "markdown-it": "~14.1.1", "markdownlint": "~0.40.0", - "minimatch": "~10.1.1", + "minimatch": "~10.2.4", "run-con": "~1.3.2", - "smol-toml": "~1.5.2", + "smol-toml": "~1.6.0", "tinyglobby": "~0.2.15" }, "bin": { @@ -12654,16 +12606,15 @@ "dev": true }, "node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, - "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.5" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -13074,11 +13025,10 @@ } }, "node_modules/normalize-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", - "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.1.tgz", + "integrity": "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.16" }, @@ -13087,11 +13037,10 @@ } }, "node_modules/npm-check-updates": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-19.2.0.tgz", - "integrity": "sha512-XSIuL0FNgzXPDZa4lje7+OwHjiyEt84qQm6QMsQRbixNY5EHEM9nhgOjxjlK9jIbN+ysvSqOV8DKNS0zydwbdg==", + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-20.0.1.tgz", + "integrity": "sha512-YuzpyL1Od5dJzpeETVh2H5o1I8tpi0zkf6v7k7rXwUDfiDliBX9dgVIb7FlEfp8Lu2RtECAv63ZHm/rqpIhYsw==", "dev": true, - "license": "Apache-2.0", "bin": { "ncu": "build/cli.js", "npm-check-updates": "build/cli.js" @@ -16500,11 +16449,10 @@ } }, "node_modules/smol-toml": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.5.2.tgz", - "integrity": "sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", + "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">= 18" }, @@ -17454,11 +17402,10 @@ "dev": true }, "node_modules/svgo": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", - "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz", + "integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==", "dev": true, - "license": "MIT", "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", @@ -17466,7 +17413,7 @@ "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", - "sax": "^1.4.1" + "sax": "^1.5.0" }, "bin": { "svgo": "bin/svgo.js" @@ -17490,11 +17437,25 @@ } }, "node_modules/svgo/node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", "dev": true, - "license": "ISC" + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "dev": true, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/tapable": { "version": "1.1.3", @@ -18130,13 +18091,15 @@ "dev": true }, "node_modules/type-fest": { - "version": "4.26.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", - "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz", + "integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, "engines": { - "node": ">=16" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -18266,6 +18229,18 @@ "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", "dev": true }, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -19072,9 +19047,9 @@ } }, "node_modules/vuepress-theme-titanium": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/vuepress-theme-titanium/-/vuepress-theme-titanium-4.11.2.tgz", - "integrity": "sha512-a/MQ2H4bJKl7D97RT5E4DfBnUWewTmjNcoCKhwI3zrfWUnxeQWuGjnrdaswSm7t6YiUHkJIBrMsCJNPIiHY5EA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vuepress-theme-titanium/-/vuepress-theme-titanium-5.0.0.tgz", + "integrity": "sha512-hKkpt2qPIrSQEFHdaqqoBa5oKIlQ+CKMdWO7NcC0T9TGOtbh8yZOTjAN5dxoT7UXsYtv86Le4K2pnuKk1Ceeeg==", "dev": true, "dependencies": { "@vuepress/plugin-nprogress": "^1.7.1", diff --git a/package.json b/package.json index 29f5c9dc6..2d9664627 100644 --- a/package.json +++ b/package.json @@ -24,16 +24,16 @@ "devDependencies": { "@vuepress/plugin-back-to-top": "^1.9.10", "@vuepress/plugin-medium-zoom": "^1.9.10", - "got": "^14.6.5", + "got": "^15.0.1", "husky": "^9.1.7", - "markdownlint-cli": "^0.47.0", - "npm-check-updates": "^19.2.0", + "markdownlint-cli": "^0.48.0", + "npm-check-updates": "^20.0.1", "plantuml-encoder": "^1.4.0", - "svgo": "^4.0.0", + "svgo": "^4.0.1", "vuepress": "^1.9.10", "vuepress-plugin-mermaidjs": "^2.0.0-beta.2", "vuepress-plugin-versioning": "git+https://github.com/mojaloop/vuepress-plugin-versioning.git#dcb14962a69b8e5aaf184d2d1a31ae4f43870bc1", - "vuepress-theme-titanium": "^4.11.2" + "vuepress-theme-titanium": "^5.0.0" }, "overrides": { "vuepress": { From 496c9e6eae43a3f50c06a2aee514e03bf8661c47 Mon Sep 17 00:00:00 2001 From: Sam <10507686+elnyry-sam-k@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:53:02 +0530 Subject: [PATCH 5/5] chore: changes to the PKI guide based on DA issue (#557) * Changes to the PKI guide based on DA issue: https://github.com/mojaloop/design-authority-project/issues/110 * change in version * minor package-lock json change to support "npm ci" * fix for puml script issue * chore: fixing merge conflicts * chore: regenerate package-lock.json with node 22.15.0 * chore: fix package-lock.json conflict against master --- docs/technical/api/fspiop/pki-best-practices.md | 5 ++++- scripts/_render_svg.mjs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/technical/api/fspiop/pki-best-practices.md b/docs/technical/api/fspiop/pki-best-practices.md index 5de85cb0d..8fcd2eac9 100644 --- a/docs/technical/api/fspiop/pki-best-practices.md +++ b/docs/technical/api/fspiop/pki-best-practices.md @@ -24,6 +24,7 @@ The following conventions are used in this document to identify the specified ty |Version|Date|Change Description| |---|---|---| |**1.0**|2018-03-13|Initial version| +|**2.0**|2026-04-08|Second version published to match FSPIOP v2.0 document set| ## Introduction @@ -408,7 +409,9 @@ This section describes the application layer protection. The _JSON Web Signature_ (JWS) standard is used for providing end-to-end integrity and non-repudiation; that is, to guarantee that the sender is who it claims to be, and that the message was not tampered with. -The use of JWS is mandatory and certificates should be used. For more information, see _API Signature_. +The use of JWS is mandatory and certificates must be used. For more information, see _API Signature_. + +JWS's core purpose includes non-repudiation i.e., proving who signed a message. A bare symmetric key (HMAC) can prove a message wasn't tampered with, but can't prove which party signed it since both sides share the same key. Only an asymmetric certificate tied to a CA-verified identity achieves true non-repudiation. The entire PKI model - where each platform trusts a shared CA only works if JWS signatures are certificate-backed. Without it, a platform could generate any key pair and claim any identity. Certificates anchor identity to the CA's vetting process. ### JSON Web Encryption diff --git a/scripts/_render_svg.mjs b/scripts/_render_svg.mjs index 73a529b68..aa01947d5 100755 --- a/scripts/_render_svg.mjs +++ b/scripts/_render_svg.mjs @@ -32,7 +32,7 @@ async function main() { const rawPumlContents = fs.readFileSync(inputPath) const encoded = plantumlEncoder.encode(rawPumlContents.toString()) - const url = path.join(rendererBaseUrl, 'svg', encoded) + const url = `${rendererBaseUrl}/svg/${encoded}` let result try { result = await got.get(url)