feat: add TinyLink docs section and Mermaid diagram support
Wire TinyLink into Eleventy collections, homepage highlights, and project navigation so the new integration design page is discoverable. Enable Mermaid code fence handling in markdown and client-side rendering in the base layout, and normalize the TinyLink diagram syntax for compatibility.
This commit is contained in:
parent
ca80720bfd
commit
73f8d67ee3
25
.eleventy.js
25
.eleventy.js
@ -1,3 +1,6 @@
|
||||
const markdownIt = require("markdown-it");
|
||||
const markdownItMermaid = require("markdown-it-mermaid");
|
||||
|
||||
module.exports = function (eleventyConfig) {
|
||||
// Passthrough copy for static assets
|
||||
eleventyConfig.addPassthroughCopy("src/assets");
|
||||
@ -54,6 +57,16 @@ module.exports = function (eleventyConfig) {
|
||||
return array.slice(0, n);
|
||||
});
|
||||
|
||||
// Markdown: enable Mermaid diagrams
|
||||
const mermaidPlugin = markdownItMermaid.default || markdownItMermaid;
|
||||
const markdownLib = markdownIt({
|
||||
html: true,
|
||||
breaks: false,
|
||||
linkify: true
|
||||
}).use(mermaidPlugin);
|
||||
|
||||
eleventyConfig.setLibrary("md", markdownLib);
|
||||
|
||||
// Collections
|
||||
// Blog posts / Proposals collection
|
||||
eleventyConfig.addCollection("posts", function (collectionApi) {
|
||||
@ -62,12 +75,13 @@ module.exports = function (eleventyConfig) {
|
||||
});
|
||||
});
|
||||
|
||||
// Projects collection (blog posts + CLQMS projects)
|
||||
// Projects collection (blog posts + CLQMS + TinyLink)
|
||||
eleventyConfig.addCollection("projects", function (collectionApi) {
|
||||
const blogPosts = collectionApi.getFilteredByGlob("src/blog/**/*.md");
|
||||
const clqmsPosts = collectionApi.getFilteredByTag("clqms");
|
||||
const tinylinkPosts = collectionApi.getFilteredByTag("tinylink");
|
||||
|
||||
const allProjects = [...blogPosts, ...clqmsPosts].sort((a, b) => {
|
||||
const allProjects = [...blogPosts, ...clqmsPosts, ...tinylinkPosts].sort((a, b) => {
|
||||
return new Date(b.date) - new Date(a.date);
|
||||
});
|
||||
|
||||
@ -81,6 +95,13 @@ module.exports = function (eleventyConfig) {
|
||||
});
|
||||
});
|
||||
|
||||
// TinyLink collection sorted by order
|
||||
eleventyConfig.addCollection("tinylink", function (collectionApi) {
|
||||
return collectionApi.getFilteredByTag("tinylink").sort((a, b) => {
|
||||
return (Number(a.data.order) ?? 99) - (Number(b.data.order) ?? 99);
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
dir: {
|
||||
input: "src",
|
||||
|
||||
110
package-lock.json
generated
110
package-lock.json
generated
@ -8,6 +8,10 @@
|
||||
"name": "5panda.11ty",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"markdown-it": "^14.1.1",
|
||||
"markdown-it-mermaid": "^0.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@11ty/eleventy": "^3.1.2",
|
||||
"@tailwindcss/postcss": "^4.1.18",
|
||||
@ -659,7 +663,6 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/array-buffer-byte-length": {
|
||||
@ -1072,6 +1075,34 @@
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/d3": {
|
||||
"version": "3.5.17",
|
||||
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
|
||||
"integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/dagre-d3-renderer": {
|
||||
"version": "0.4.26",
|
||||
"resolved": "https://registry.npmjs.org/dagre-d3-renderer/-/dagre-d3-renderer-0.4.26.tgz",
|
||||
"integrity": "sha512-vOWj1uA4/APTrfDyfHaH/xpfXhPh9rszW+HOaEwPCeA6Afl06Lobfh7OpESuVMQW2QGuY4UQ7pte/p0WhdDs7w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d3": "3.5.17",
|
||||
"dagre-layout": "^0.8.0",
|
||||
"graphlib": "^2.1.1",
|
||||
"lodash": "^4.17.4"
|
||||
}
|
||||
},
|
||||
"node_modules/dagre-layout": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/dagre-layout/-/dagre-layout-0.8.8.tgz",
|
||||
"integrity": "sha512-ZNV15T9za7X+fV8Z07IZquUKugCxm5owoiPPxfEx6OJRD331nkiIaF3vSt0JEY5FkrY0KfRQxcpQ3SpXB7pLPQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graphlibrary": "^2.2.0",
|
||||
"lodash": "^4.17.5"
|
||||
}
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
||||
@ -1892,6 +1923,24 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/graphlib": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz",
|
||||
"integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"node_modules/graphlibrary": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/graphlibrary/-/graphlibrary-2.2.0.tgz",
|
||||
"integrity": "sha512-XTcvT55L8u4MBZrM37zXoUxsgxs/7sow7YSygd9CIwfWTVO8RVu7AYXhhCiTuFEf+APKgx6Jk4SuQbYR0vYKmQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.5"
|
||||
}
|
||||
},
|
||||
"node_modules/gray-matter": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
|
||||
@ -2026,6 +2075,15 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/he": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/hosted-git-info": {
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
@ -2970,7 +3028,6 @@
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"uc.micro": "^2.0.0"
|
||||
@ -3030,6 +3087,12 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.18.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
|
||||
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/luxon": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz",
|
||||
@ -3051,10 +3114,9 @@
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"version": "14.1.1",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz",
|
||||
"integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1",
|
||||
@ -3068,11 +3130,19 @@
|
||||
"markdown-it": "bin/markdown-it.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/markdown-it-mermaid": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-mermaid/-/markdown-it-mermaid-0.2.5.tgz",
|
||||
"integrity": "sha512-ZUTFRX+cXEtWmn/9LMlpVklPJiDrHPWyHE/wamC2wm0Ojh1qOcuKWfWW3BqP83+7w6C59rS7M3OrGTs/u9mQTA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mermaid": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/markdown-it/node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
@ -3111,7 +3181,6 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
||||
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/memorystream": {
|
||||
@ -3123,6 +3192,20 @@
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mermaid": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-7.1.2.tgz",
|
||||
"integrity": "sha512-bDLu3fQuf3/R0fNkNzB0GTaF7+6SxnZpfTs9DVQF1ougsuP23MBzvEIGfL0ML8zeyg7+J2D+0AaoLVhskW5ulw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d3": "3.5.17",
|
||||
"dagre-d3-renderer": "^0.4.25",
|
||||
"dagre-layout": "^0.8.0",
|
||||
"he": "^1.1.1",
|
||||
"lodash": "^4.17.4",
|
||||
"moment": "^2.20.1"
|
||||
}
|
||||
},
|
||||
"node_modules/mime": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
|
||||
@ -3196,6 +3279,15 @@
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/moo": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
|
||||
@ -3801,7 +3893,6 @@
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
|
||||
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@ -4639,7 +4730,6 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
|
||||
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
|
||||
@ -26,5 +26,9 @@
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-cli": "^11.0.1",
|
||||
"tailwindcss": "^4.1.18"
|
||||
},
|
||||
"dependencies": {
|
||||
"markdown-it": "^14.1.1",
|
||||
"markdown-it-mermaid": "^0.2.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@
|
||||
<summary>Projects</summary>
|
||||
<ul>
|
||||
<li><a href="/projects/clqms01/" class="{% if '/projects/clqms01/' in page.url %}text-primary font-medium{% endif %}">CLQMS</a></li>
|
||||
<li><a href="/projects/tinylink/001-design/" class="{% if '/projects/tinylink/' in page.url %}text-primary font-medium{% endif %}">TinyLink</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
@ -90,6 +91,11 @@
|
||||
<span class="mr-2">🏥</span>CLQMS
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/projects/tinylink/001-design/" class="{% if '/projects/tinylink/' in page.url %}text-primary bg-primary/10{% endif %} hover:text-primary hover:bg-primary/10">
|
||||
<span class="mr-2">🔗</span>TinyLink
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
@ -153,6 +159,16 @@
|
||||
<p class="text-sm text-base-content/40">© {% year %} 5Panda. Built with 11ty & Tailwind CSS.</p>
|
||||
</aside>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
const diagrams = document.querySelectorAll('.mermaid');
|
||||
if (!diagrams.length || !window.mermaid) return;
|
||||
|
||||
mermaid.initialize({ startOnLoad: false, securityLevel: 'loose' });
|
||||
mermaid.run({ nodes: diagrams });
|
||||
})();
|
||||
</script>
|
||||
<!-- Theme toggle script -->
|
||||
<script>
|
||||
document.getElementById('theme-toggle').addEventListener('click', function () {
|
||||
@ -166,4 +182,4 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@ -110,3 +110,36 @@ description: Innovative projects and ideas
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<!-- TinyLink Section -->
|
||||
{% if collections.tinylink.length > 0 %}
|
||||
<section class="py-20">
|
||||
<div class="section-container-wide">
|
||||
<div class="text-center mb-12">
|
||||
<span class="badge badge-outline mb-4">TinyLink</span>
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-4">Integration Hub</h2>
|
||||
<p class="text-base-content/70 max-w-2xl mx-auto">
|
||||
Bi-directional instrument integration and message translation workflows.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl mx-auto">
|
||||
{% for post in collections.tinylink | head(4) %}
|
||||
<a href="{{ post.url }}" class="post-card group">
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<span class="text-sm text-base-content/50">TinyLink</span>
|
||||
<span class="text-base-content/30">•</span>
|
||||
<span class="text-sm text-base-content/50">{{ post.content | readingTime }}</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold mb-2 group-hover:text-primary transition-colors">{{ post.data.title }}</h3>
|
||||
<p class="text-base-content/70">{{ post.data.description | excerpt(120) }}</p>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if collections.tinylink.length > 4 %}
|
||||
<div class="text-center mt-10">
|
||||
<a href="/projects/tinylink/001-design/" class="btn btn-outline">View TinyLink Docs</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
84
src/projects/tinylink/001-design.md
Normal file
84
src/projects/tinylink/001-design.md
Normal file
@ -0,0 +1,84 @@
|
||||
---
|
||||
layout: post.njk
|
||||
tags: tinylink
|
||||
title: "TinyLink: Integration Design"
|
||||
description: "Bi-directional integration hub design for instrument results and CLQMS01 workflows."
|
||||
date: 2026-04-07
|
||||
order: 1
|
||||
---
|
||||
|
||||
# TinyLink Integration Design
|
||||
|
||||
## Overview
|
||||
TinyLink is a bi-directional integration hub between laboratory instruments and the CLQMS01 host. It receives instrument results, wraps raw payloads into a canonical envelope, translates them to JSON, and pushes them to CLQMS01. It also retrieves test requests from CLQMS01 and delivers them to instruments through download and query workflows (planned).
|
||||
|
||||
## Goals
|
||||
- Provide reliable, automated data exchange between instruments and CLQMS01.
|
||||
- Normalize and translate messages between instrument formats and JSON for CLQMS01.
|
||||
- Support both download (new requests) and query (SampleID) workflows.
|
||||
|
||||
## Non-Goals
|
||||
- User interface or manual data entry.
|
||||
- Business rule orchestration beyond mapping and routing.
|
||||
- Long-term analytics or reporting.
|
||||
|
||||
## High-Level Architecture
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph Instrument
|
||||
INST[Instrument]
|
||||
end
|
||||
|
||||
subgraph App
|
||||
RCV[Receiver / Raw Capture]
|
||||
XLT[Translator]
|
||||
ROUTE[Message Router - planned]
|
||||
POLL[Scheduler / Poller - planned]
|
||||
end
|
||||
|
||||
subgraph CLQMS01
|
||||
CLQ[CLQMS01 Host]
|
||||
end
|
||||
|
||||
%% Result flow
|
||||
INST -->|Result data| RCV
|
||||
RCV --> XLT
|
||||
XLT -->|JSON| CLQ
|
||||
|
||||
%% Download request flow
|
||||
POLL -->|Check new requests| CLQ
|
||||
CLQ -->|New requests| ROUTE
|
||||
ROUTE -->|Instrument message| INST
|
||||
|
||||
%% Query flow
|
||||
INST -->|Query + SampleID| ROUTE
|
||||
ROUTE -->|SampleID| CLQ
|
||||
CLQ -->|Ordered tests| XLT
|
||||
XLT -->|Instrument response| INST
|
||||
```
|
||||
|
||||
## Data Flows
|
||||
- Result flow (Instrument → CLQMS01): receive instrument output, wrap raw payload into a canonical envelope, translate to JSON, send to CLQMS01.
|
||||
- Download request flow (CLQMS01 → Instrument): poll CLQMS01 for new requests, map to instrument message, send to instrument. (planned)
|
||||
- Query flow (Instrument → CLQMS01 → Instrument): instrument sends query with SampleID, fetch ordered tests from CLQMS01, translate to instrument response, send back. (planned)
|
||||
|
||||
## Current vs Planned
|
||||
- Current: result ingest → raw capture → translator → queue → delivery worker → CLQMS01.
|
||||
- Planned: scheduler/poller for download requests and message router for download/query workflows.
|
||||
|
||||
## Key Components
|
||||
- Receiver/Raw Capture: accepts instrument output and records it as raw payload for translation.
|
||||
- Translator: maps instrument fields to JSON schema and vice versa.
|
||||
- Message Router: routes messages to the correct workflow and destination. (planned)
|
||||
- Scheduler/Poller: periodically checks CLQMS01 for new requests. (planned)
|
||||
- CLQMS01 Adapter: handles request/response and authentication to the host.
|
||||
|
||||
## Reliability and Error Handling
|
||||
- Retry on transient network failures.
|
||||
- Log and flag translation/normalization errors with raw payload references.
|
||||
- Idempotency safeguards for resends when possible.
|
||||
|
||||
## Security and Configuration
|
||||
- CLQMS01 host and API key stored in config.
|
||||
- Instrument connection details stored in config.
|
||||
- No secrets committed to source control.
|
||||
Loading…
x
Reference in New Issue
Block a user