1395 lines
59 KiB
HTML
1395 lines
59 KiB
HTML
|
|
<!doctype html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8" />
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
|
|
<title
|
||
|
|
data-en="Provisioning - Infrastructure Orchestration Platform"
|
||
|
|
data-es="Provisioning - Plataforma de Orquestación de Infraestructura"
|
||
|
|
>
|
||
|
|
Provisioning
|
||
|
|
</title>
|
||
|
|
<link
|
||
|
|
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700;800&display=swap"
|
||
|
|
rel="stylesheet"
|
||
|
|
/>
|
||
|
|
<style>
|
||
|
|
:root {
|
||
|
|
--bg-primary: #0a0118;
|
||
|
|
--bg-secondary: rgba(255, 255, 255, 0.03);
|
||
|
|
--text-primary: #ffffff;
|
||
|
|
--text-secondary: #cbd5e1;
|
||
|
|
--text-muted: #94a3b8;
|
||
|
|
--border-color: rgba(16, 185, 129, 0.3);
|
||
|
|
--border-color-light: rgba(59, 130, 246, 0.3);
|
||
|
|
--accent-green: #10b981;
|
||
|
|
--accent-blue: #3b82f6;
|
||
|
|
--accent-purple: #8b5cf6;
|
||
|
|
--card-bg: rgba(255, 255, 255, 0.03);
|
||
|
|
--card-border: rgba(59, 130, 246, 0.3);
|
||
|
|
--highlight-color: #10b981;
|
||
|
|
--footer-text: #64748b;
|
||
|
|
}
|
||
|
|
|
||
|
|
html.light-mode {
|
||
|
|
--bg-primary: #f3f4f6;
|
||
|
|
--bg-secondary: rgba(0, 0, 0, 0.02);
|
||
|
|
--text-primary: #111827;
|
||
|
|
--text-secondary: #374151;
|
||
|
|
--text-muted: #6b7280;
|
||
|
|
--border-color: rgba(16, 185, 129, 0.4);
|
||
|
|
--border-color-light: rgba(59, 130, 246, 0.4);
|
||
|
|
--accent-green: #059669;
|
||
|
|
--accent-blue: #2563eb;
|
||
|
|
--accent-purple: #7c3aed;
|
||
|
|
--card-bg: rgba(0, 0, 0, 0.02);
|
||
|
|
--card-border: rgba(59, 130, 246, 0.3);
|
||
|
|
--highlight-color: #059669;
|
||
|
|
--footer-text: #4b5563;
|
||
|
|
}
|
||
|
|
|
||
|
|
* {
|
||
|
|
margin: 0;
|
||
|
|
padding: 0;
|
||
|
|
box-sizing: border-box;
|
||
|
|
}
|
||
|
|
|
||
|
|
body {
|
||
|
|
font-family: "JetBrains Mono", monospace;
|
||
|
|
background: var(--bg-primary);
|
||
|
|
color: var(--text-primary);
|
||
|
|
overflow-x: hidden;
|
||
|
|
transition:
|
||
|
|
background-color 0.3s ease,
|
||
|
|
color 0.3s ease;
|
||
|
|
}
|
||
|
|
|
||
|
|
.gradient-bg {
|
||
|
|
position: fixed;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
z-index: -1;
|
||
|
|
background:
|
||
|
|
radial-gradient(
|
||
|
|
circle at 20% 50%,
|
||
|
|
var(--accent-blue) 0%,
|
||
|
|
transparent 50%
|
||
|
|
),
|
||
|
|
radial-gradient(
|
||
|
|
circle at 80% 80%,
|
||
|
|
var(--accent-green) 0%,
|
||
|
|
transparent 50%
|
||
|
|
),
|
||
|
|
radial-gradient(
|
||
|
|
circle at 40% 90%,
|
||
|
|
var(--accent-purple) 0%,
|
||
|
|
transparent 50%
|
||
|
|
);
|
||
|
|
opacity: 0.15;
|
||
|
|
}
|
||
|
|
|
||
|
|
.language-toggle {
|
||
|
|
position: fixed;
|
||
|
|
top: 2rem;
|
||
|
|
right: 2rem;
|
||
|
|
z-index: 100;
|
||
|
|
display: flex;
|
||
|
|
gap: 0.5rem;
|
||
|
|
background: var(--bg-primary);
|
||
|
|
border: 1px solid var(--border-color);
|
||
|
|
border-radius: 20px;
|
||
|
|
padding: 0.3rem 0.3rem;
|
||
|
|
backdrop-filter: blur(10px);
|
||
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||
|
|
}
|
||
|
|
|
||
|
|
.lang-btn {
|
||
|
|
background: transparent;
|
||
|
|
border: none;
|
||
|
|
color: var(--text-muted);
|
||
|
|
padding: 0.5rem 1rem;
|
||
|
|
border-radius: 18px;
|
||
|
|
cursor: pointer;
|
||
|
|
font-weight: 700;
|
||
|
|
font-size: 0.85rem;
|
||
|
|
text-transform: uppercase;
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
font-family: "JetBrains Mono", monospace;
|
||
|
|
}
|
||
|
|
|
||
|
|
.lang-btn.active {
|
||
|
|
background: linear-gradient(135deg, #10b981 0%, #3b82f6 100%);
|
||
|
|
color: #fff;
|
||
|
|
}
|
||
|
|
|
||
|
|
.lang-btn:hover {
|
||
|
|
color: var(--highlight-color);
|
||
|
|
}
|
||
|
|
|
||
|
|
.container {
|
||
|
|
max-width: 1200px;
|
||
|
|
margin: 0 auto;
|
||
|
|
padding: 2rem;
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
|
||
|
|
header {
|
||
|
|
text-align: center;
|
||
|
|
padding: 5rem 0 2rem;
|
||
|
|
animation: fadeInUp 0.8s ease-out;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes fadeInUp {
|
||
|
|
from {
|
||
|
|
opacity: 0;
|
||
|
|
transform: translateY(30px);
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
opacity: 1;
|
||
|
|
transform: translateY(0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-badge {
|
||
|
|
display: inline-block;
|
||
|
|
background: rgba(16, 185, 129, 0.2);
|
||
|
|
border: 1px solid #10b981;
|
||
|
|
color: #10b981;
|
||
|
|
padding: 0.5rem 1.5rem;
|
||
|
|
border-radius: 50px;
|
||
|
|
font-size: 0.85rem;
|
||
|
|
font-weight: 700;
|
||
|
|
margin-bottom: 1.5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.logo-container {
|
||
|
|
margin-bottom: 2rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.logo-container img {
|
||
|
|
max-width: 440px;
|
||
|
|
width: 100%;
|
||
|
|
height: auto;
|
||
|
|
filter: drop-shadow(0 0 30px rgba(16, 185, 129, 0.4));
|
||
|
|
}
|
||
|
|
|
||
|
|
.tagline {
|
||
|
|
font-size: 0.95rem;
|
||
|
|
color: #10b981;
|
||
|
|
font-weight: 400;
|
||
|
|
letter-spacing: 0.1em;
|
||
|
|
text-transform: uppercase;
|
||
|
|
margin-bottom: 1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
h1 {
|
||
|
|
font-size: 2.8rem;
|
||
|
|
font-weight: 800;
|
||
|
|
line-height: 1.2;
|
||
|
|
margin-bottom: 1.5rem;
|
||
|
|
background: linear-gradient(
|
||
|
|
135deg,
|
||
|
|
#10b981 0%,
|
||
|
|
#3b82f6 50%,
|
||
|
|
#8b5cf6 100%
|
||
|
|
);
|
||
|
|
-webkit-background-clip: text;
|
||
|
|
-webkit-text-fill-color: transparent;
|
||
|
|
background-clip: text;
|
||
|
|
}
|
||
|
|
|
||
|
|
.hero-subtitle {
|
||
|
|
font-size: 1.15rem;
|
||
|
|
color: var(--text-secondary);
|
||
|
|
max-width: 800px;
|
||
|
|
margin: 0 auto 2rem;
|
||
|
|
line-height: 1.8;
|
||
|
|
}
|
||
|
|
|
||
|
|
.highlight {
|
||
|
|
color: var(--highlight-color);
|
||
|
|
font-weight: 700;
|
||
|
|
}
|
||
|
|
|
||
|
|
.section {
|
||
|
|
margin: 4rem 0;
|
||
|
|
animation: fadeInUp 0.8s ease-out;
|
||
|
|
}
|
||
|
|
.section-0 {
|
||
|
|
margin: 0.2rem 0;
|
||
|
|
}
|
||
|
|
.section-title {
|
||
|
|
font-size: 2rem;
|
||
|
|
font-weight: 800;
|
||
|
|
margin-bottom: 2rem;
|
||
|
|
color: #10b981;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.section-title span {
|
||
|
|
background: linear-gradient(135deg, #8b5cf6 0%, #3b82f6 100%);
|
||
|
|
-webkit-background-clip: text;
|
||
|
|
-webkit-text-fill-color: transparent;
|
||
|
|
background-clip: text;
|
||
|
|
}
|
||
|
|
|
||
|
|
.problems-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||
|
|
gap: 1.5rem;
|
||
|
|
margin-top: 2rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.problem-card {
|
||
|
|
background: var(--card-bg);
|
||
|
|
border: 1px solid var(--border-color-light);
|
||
|
|
border-radius: 12px;
|
||
|
|
padding: 2rem;
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
position: relative;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
.problem-card:hover {
|
||
|
|
transform: translateY(-5px);
|
||
|
|
background: rgba(255, 255, 255, 0.05);
|
||
|
|
border-color: rgba(16, 185, 129, 0.5);
|
||
|
|
}
|
||
|
|
|
||
|
|
.problem-number {
|
||
|
|
font-size: 2rem;
|
||
|
|
font-weight: 800;
|
||
|
|
background: linear-gradient(135deg, #10b981 0%, #3b82f6 100%);
|
||
|
|
-webkit-background-clip: text;
|
||
|
|
-webkit-text-fill-color: transparent;
|
||
|
|
background-clip: text;
|
||
|
|
line-height: 1;
|
||
|
|
margin-bottom: 0.5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.problem-card h3 {
|
||
|
|
color: #8b5cf6;
|
||
|
|
font-size: 1.05rem;
|
||
|
|
margin-bottom: 0.7rem;
|
||
|
|
font-weight: 700;
|
||
|
|
}
|
||
|
|
|
||
|
|
.problem-card p {
|
||
|
|
color: var(--text-secondary);
|
||
|
|
font-size: 0.9rem;
|
||
|
|
line-height: 1.6;
|
||
|
|
}
|
||
|
|
|
||
|
|
.tech-stack {
|
||
|
|
display: flex;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
gap: 1rem;
|
||
|
|
margin-top: 2rem;
|
||
|
|
justify-content: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.tech-badge {
|
||
|
|
background: rgba(16, 185, 129, 0.15);
|
||
|
|
border: 1px solid #10b981;
|
||
|
|
padding: 0.5rem 1rem;
|
||
|
|
border-radius: 20px;
|
||
|
|
font-size: 0.8rem;
|
||
|
|
color: #10b981;
|
||
|
|
font-weight: 700;
|
||
|
|
}
|
||
|
|
|
||
|
|
.features-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||
|
|
gap: 2rem;
|
||
|
|
margin-top: 2rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.feature-box {
|
||
|
|
background: linear-gradient(
|
||
|
|
135deg,
|
||
|
|
rgba(16, 185, 129, 0.1) 0%,
|
||
|
|
rgba(59, 130, 246, 0.1) 100%
|
||
|
|
);
|
||
|
|
border-radius: 12px;
|
||
|
|
padding: 2rem;
|
||
|
|
border-left: 4px solid #10b981;
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
}
|
||
|
|
|
||
|
|
.feature-box:hover {
|
||
|
|
background: linear-gradient(
|
||
|
|
135deg,
|
||
|
|
rgba(16, 185, 129, 0.15) 0%,
|
||
|
|
rgba(59, 130, 246, 0.15) 100%
|
||
|
|
);
|
||
|
|
transform: translateY(-3px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.feature-icon {
|
||
|
|
font-size: 2.5rem;
|
||
|
|
margin-bottom: 1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.feature-title {
|
||
|
|
font-size: 1.15rem;
|
||
|
|
font-weight: 700;
|
||
|
|
color: #10b981;
|
||
|
|
margin-bottom: 0.7rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.feature-text {
|
||
|
|
color: var(--text-secondary);
|
||
|
|
font-size: 0.95rem;
|
||
|
|
line-height: 1.7;
|
||
|
|
}
|
||
|
|
|
||
|
|
.components-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||
|
|
gap: 1rem;
|
||
|
|
margin-top: 2rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.component-item {
|
||
|
|
background: rgba(139, 92, 246, 0.1);
|
||
|
|
padding: 1.2rem;
|
||
|
|
border-radius: 8px;
|
||
|
|
font-size: 0.9rem;
|
||
|
|
border: 1px solid rgba(139, 92, 246, 0.3);
|
||
|
|
transition: all 0.2s ease;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.component-item:hover {
|
||
|
|
background: rgba(139, 92, 246, 0.15);
|
||
|
|
transform: translateY(-2px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.component-name {
|
||
|
|
color: #8b5cf6;
|
||
|
|
font-weight: 700;
|
||
|
|
display: block;
|
||
|
|
margin-bottom: 0.3rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.component-role {
|
||
|
|
color: var(--text-muted);
|
||
|
|
font-size: 0.85rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.cta-section {
|
||
|
|
text-align: center;
|
||
|
|
margin: 5rem 0 3rem;
|
||
|
|
padding: 4rem 2rem;
|
||
|
|
background: linear-gradient(
|
||
|
|
135deg,
|
||
|
|
rgba(16, 185, 129, 0.1) 0%,
|
||
|
|
rgba(139, 92, 246, 0.1) 100%
|
||
|
|
);
|
||
|
|
border-radius: 20px;
|
||
|
|
border: 1px solid rgba(59, 130, 246, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.cta-title {
|
||
|
|
font-size: 2rem;
|
||
|
|
font-weight: 800;
|
||
|
|
margin-bottom: 1rem;
|
||
|
|
background: linear-gradient(135deg, #10b981 0%, #8b5cf6 100%);
|
||
|
|
-webkit-background-clip: text;
|
||
|
|
-webkit-text-fill-color: transparent;
|
||
|
|
background-clip: text;
|
||
|
|
}
|
||
|
|
|
||
|
|
.cta-button {
|
||
|
|
display: inline-block;
|
||
|
|
background: linear-gradient(
|
||
|
|
135deg,
|
||
|
|
#10b981 0%,
|
||
|
|
#3b82f6 50%,
|
||
|
|
#8b5cf6 100%
|
||
|
|
);
|
||
|
|
color: #fff;
|
||
|
|
padding: 1.1rem 2.8rem;
|
||
|
|
border-radius: 50px;
|
||
|
|
text-decoration: none;
|
||
|
|
font-weight: 800;
|
||
|
|
font-size: 1rem;
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
box-shadow: 0 10px 30px rgba(16, 185, 129, 0.3);
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.05em;
|
||
|
|
border: none;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
|
||
|
|
.cta-button:hover {
|
||
|
|
transform: translateY(-3px) scale(1.05);
|
||
|
|
box-shadow: 0 20px 50px rgba(16, 185, 129, 0.5);
|
||
|
|
}
|
||
|
|
|
||
|
|
footer {
|
||
|
|
text-align: center;
|
||
|
|
padding: 3rem 0 2rem;
|
||
|
|
color: var(--footer-text);
|
||
|
|
border-top: 1px solid var(--border-color);
|
||
|
|
margin-top: 4rem;
|
||
|
|
font-size: 0.9rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
footer p:first-child {
|
||
|
|
font-weight: 700;
|
||
|
|
color: #94a3b8;
|
||
|
|
}
|
||
|
|
|
||
|
|
footer p:last-child {
|
||
|
|
margin-top: 0.5rem;
|
||
|
|
font-size: 0.85rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.hidden {
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.theme-toggle {
|
||
|
|
background: transparent;
|
||
|
|
border: none;
|
||
|
|
color: var(--text-muted);
|
||
|
|
padding: 0.5rem 1rem;
|
||
|
|
border-radius: 18px;
|
||
|
|
cursor: pointer;
|
||
|
|
font-weight: 700;
|
||
|
|
font-size: 1.2rem;
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
}
|
||
|
|
|
||
|
|
.theme-toggle:hover {
|
||
|
|
color: var(--accent-green);
|
||
|
|
}
|
||
|
|
|
||
|
|
.repo-link {
|
||
|
|
display: inline-block;
|
||
|
|
margin-top: 0.6rem;
|
||
|
|
font-family: "JetBrains Mono", monospace;
|
||
|
|
font-size: 0.75rem;
|
||
|
|
font-weight: 700;
|
||
|
|
color: var(--accent-green);
|
||
|
|
text-decoration: none;
|
||
|
|
opacity: 0.75;
|
||
|
|
letter-spacing: 0.03em;
|
||
|
|
transition: opacity 0.2s ease;
|
||
|
|
}
|
||
|
|
|
||
|
|
.repo-link:hover {
|
||
|
|
opacity: 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
.component-link {
|
||
|
|
color: inherit;
|
||
|
|
text-decoration: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.component-link:hover {
|
||
|
|
text-decoration: underline;
|
||
|
|
text-underline-offset: 2px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.arch-preview {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
gap: 1.5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.arch-img-link {
|
||
|
|
display: block;
|
||
|
|
width: 100%;
|
||
|
|
max-width: 820px;
|
||
|
|
border-radius: 12px;
|
||
|
|
overflow: hidden;
|
||
|
|
border: 1px solid var(--border-color);
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
|
||
|
|
.arch-img-link:hover {
|
||
|
|
border-color: rgba(16, 185, 129, 0.6);
|
||
|
|
box-shadow: 0 8px 32px rgba(16, 185, 129, 0.15);
|
||
|
|
transform: translateY(-2px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.arch-img {
|
||
|
|
display: block;
|
||
|
|
width: 100%;
|
||
|
|
height: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
html.light-mode .arch-dark { display: none; }
|
||
|
|
html:not(.light-mode) .arch-light { display: none; }
|
||
|
|
|
||
|
|
.arch-btn {
|
||
|
|
display: inline-block;
|
||
|
|
border: 2px solid #10b981;
|
||
|
|
color: #10b981;
|
||
|
|
padding: 0.9rem 2.4rem;
|
||
|
|
border-radius: 50px;
|
||
|
|
text-decoration: none;
|
||
|
|
font-weight: 800;
|
||
|
|
font-size: 0.95rem;
|
||
|
|
font-family: "JetBrains Mono", monospace;
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.05em;
|
||
|
|
}
|
||
|
|
|
||
|
|
.arch-btn:hover {
|
||
|
|
background: #10b981;
|
||
|
|
color: #fff;
|
||
|
|
box-shadow: 0 10px 30px rgba(16, 185, 129, 0.3);
|
||
|
|
transform: translateY(-2px);
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 768px) {
|
||
|
|
h1 {
|
||
|
|
font-size: 2rem;
|
||
|
|
}
|
||
|
|
.hero-subtitle {
|
||
|
|
font-size: 1rem;
|
||
|
|
}
|
||
|
|
.logo-container img {
|
||
|
|
max-width: 352px;
|
||
|
|
}
|
||
|
|
.section-title {
|
||
|
|
font-size: 1.6rem;
|
||
|
|
}
|
||
|
|
.cta-title {
|
||
|
|
font-size: 1.6rem;
|
||
|
|
}
|
||
|
|
.language-toggle {
|
||
|
|
top: 1rem;
|
||
|
|
right: 1rem;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="gradient-bg"></div>
|
||
|
|
|
||
|
|
<div class="language-toggle">
|
||
|
|
<button
|
||
|
|
class="lang-btn active"
|
||
|
|
data-lang="en"
|
||
|
|
onclick="switchLanguage('en')"
|
||
|
|
>
|
||
|
|
EN
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
class="lang-btn"
|
||
|
|
data-lang="es"
|
||
|
|
onclick="switchLanguage('es')"
|
||
|
|
>
|
||
|
|
ES
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
class="theme-toggle"
|
||
|
|
onclick="toggleTheme()"
|
||
|
|
title="Toggle light/dark mode"
|
||
|
|
>
|
||
|
|
<span id="theme-icon">🌙</span>
|
||
|
|
</button>
|
||
|
|
<a
|
||
|
|
href="architecture-diagram.html"
|
||
|
|
class="lang-btn"
|
||
|
|
style="
|
||
|
|
text-decoration: none;
|
||
|
|
background: rgba(16, 185, 129, 0.2);
|
||
|
|
border: 1px solid rgba(16, 185, 129, 0.5);
|
||
|
|
cursor: pointer;
|
||
|
|
"
|
||
|
|
>
|
||
|
|
🏗️ ARCHITECTURE
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="container">
|
||
|
|
<header>
|
||
|
|
<span
|
||
|
|
class="status-badge"
|
||
|
|
style="display: none"
|
||
|
|
data-en="✅ v3.0.11 | Production Ready"
|
||
|
|
data-es="✅ v3.0.11 | Listo para Producción"
|
||
|
|
>✅ v3.0.11 | Production Ready</span
|
||
|
|
>
|
||
|
|
<div class="logo-container">
|
||
|
|
<img
|
||
|
|
src="provisioning.svg"
|
||
|
|
alt="Provisioning Logo"
|
||
|
|
width="300"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div class="logo-container">
|
||
|
|
<img src="logo-text.svg" alt="Provisioning" width="500" />
|
||
|
|
</div>
|
||
|
|
<p class="tagline">Provision at Scale</p>
|
||
|
|
<h1
|
||
|
|
data-en="Infrastructure Orchestration<br>With Configuration as Code"
|
||
|
|
data-es="Orquestación de Infraestructura<br>Con Configuración como Código"
|
||
|
|
>
|
||
|
|
Infrastructure Orchestration
|
||
|
|
</h1>
|
||
|
|
<p class="hero-subtitle">
|
||
|
|
<span
|
||
|
|
class="highlight"
|
||
|
|
data-en="Declarative infrastructure"
|
||
|
|
data-es="Infraestructura declarativa"
|
||
|
|
>Declarative infrastructure
|
||
|
|
</span>
|
||
|
|
<span
|
||
|
|
data-en=" management with Nickel schemas, Nushell orchestration, and Rust executables. Type-safe configuration, automated validation, and cloud-native deployment across Kubernetes, Docker, and custom platforms."
|
||
|
|
data-es=" management con esquemas Nickel, orquestación Nushell y ejecutables Rust. Configuración type-safe, validación automática y despliegue cloud-native en Kubernetes, Docker y plataformas personalizadas."
|
||
|
|
>management with Nickel schemas, Nushell orchestration,
|
||
|
|
and Rust executables. Type-safe configuration, automated
|
||
|
|
validation, and cloud-native deployment across
|
||
|
|
Kubernetes, Docker, and custom platforms.
|
||
|
|
</span>
|
||
|
|
<br /><span
|
||
|
|
><strong
|
||
|
|
data-en="100% infrastructure as code."
|
||
|
|
data-es="100% infraestructura como código."
|
||
|
|
>100% infrastructure as code.</strong
|
||
|
|
>
|
||
|
|
</span>
|
||
|
|
</p>
|
||
|
|
</header>
|
||
|
|
|
||
|
|
<section class="section-0">
|
||
|
|
<h2 class="section-title">
|
||
|
|
<span
|
||
|
|
data-en="Core Capabilities"
|
||
|
|
data-es="Capacidades Principales"
|
||
|
|
>Core Capabilities</span
|
||
|
|
>
|
||
|
|
</h2>
|
||
|
|
<div class="problems-grid">
|
||
|
|
<div class="problem-card">
|
||
|
|
<div class="problem-number">01</div>
|
||
|
|
<h3
|
||
|
|
data-en="Type-Safe Configuration"
|
||
|
|
data-es="Configuración Type-Safe"
|
||
|
|
>
|
||
|
|
Type-Safe Configuration
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
data-en="Nickel provides formal type checking, automated validation, and recursive merging for infrastructure definitions. Eliminate configuration drift and parsing errors."
|
||
|
|
data-es="Nickel proporciona verificación formal de tipos, validación automática y fusión recursiva para definiciones de infraestructura. Elimina desviación de configuración y errores de análisis."
|
||
|
|
>
|
||
|
|
Nickel provides formal type checking, automated
|
||
|
|
validation, and recursive merging for infrastructure
|
||
|
|
definitions. Eliminate configuration drift and
|
||
|
|
parsing errors.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div class="problem-card">
|
||
|
|
<div class="problem-number">02</div>
|
||
|
|
<h3
|
||
|
|
data-en="Intelligent Orchestration"
|
||
|
|
data-es="Orquestación Inteligente"
|
||
|
|
>
|
||
|
|
Intelligent Orchestration
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
data-en="Nushell scripts orchestrate complex deployment workflows with structured data pipelines, state management, and error recovery. Built-in type system prevents runtime failures."
|
||
|
|
data-es="Los scripts Nushell orquestan flujos de despliegue complejos con canales de datos estructurados, gestión de estado y recuperación de errores. Sistema de tipos incorporado previene fallos en tiempo de ejecución."
|
||
|
|
>
|
||
|
|
Nushell scripts orchestrate complex deployment
|
||
|
|
workflows with structured data pipelines, state
|
||
|
|
management, and error recovery. Built-in type system
|
||
|
|
prevents runtime failures.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div class="problem-card">
|
||
|
|
<div class="problem-number">03</div>
|
||
|
|
<h3
|
||
|
|
data-en="Multi-Platform Support"
|
||
|
|
data-es="Soporte Multi-Plataforma"
|
||
|
|
>
|
||
|
|
Multi-Platform Support
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
data-en="Deploy to Kubernetes, Docker Compose, local VMs, and custom infrastructure. Unified interface with platform-specific overrides and workspace isolation."
|
||
|
|
data-es="Despliegua en Kubernetes, Docker Compose, máquinas virtuales locales e infraestructura personalizada. Interfaz unificada con sobrescrituras específicas de plataforma y aislamiento de espacios de trabajo."
|
||
|
|
>
|
||
|
|
Deploy to Kubernetes, Docker Compose, local VMs, and
|
||
|
|
custom infrastructure. Unified interface with
|
||
|
|
platform-specific overrides and workspace isolation.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div class="problem-card">
|
||
|
|
<div class="problem-number">04</div>
|
||
|
|
<h3
|
||
|
|
data-en="Version Control Ready"
|
||
|
|
data-es="Listo para Control de Versiones"
|
||
|
|
>
|
||
|
|
Version Control Ready
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
data-en="All infrastructure lives in Git. Configuration schemas, Nickel modules, and Nushell scripts are versionable, reviewable, and rollbackable."
|
||
|
|
data-es="Toda la infraestructura vive en Git. Los esquemas de configuración, módulos Nickel y scripts Nushell son versionables, revisables y reversibles."
|
||
|
|
>
|
||
|
|
All infrastructure lives in Git. Configuration
|
||
|
|
schemas, Nickel modules, and Nushell scripts are
|
||
|
|
versionable, reviewable, and rollbackable.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<section class="section">
|
||
|
|
<h2 class="section-title">
|
||
|
|
<span data-en="How It Works" data-es="Cómo Funciona"
|
||
|
|
>How It Works</span
|
||
|
|
>
|
||
|
|
</h2>
|
||
|
|
<div class="features-grid">
|
||
|
|
<div class="feature-box">
|
||
|
|
<div class="feature-icon">📝</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
data-en="Define with Nickel"
|
||
|
|
data-es="Definir con Nickel"
|
||
|
|
>
|
||
|
|
Define with Nickel
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="Write declarative infrastructure schemas with full type safety. Nickel's lazy evaluation and recursive merging enable powerful abstractions and configuration composition."
|
||
|
|
data-es="Escriba esquemas de infraestructura declarativos con seguridad de tipos completa. La evaluación perezosa de Nickel y la fusión recursiva permiten abstracciones poderosas y composición de configuración."
|
||
|
|
>
|
||
|
|
Write declarative infrastructure schemas with full
|
||
|
|
type safety. Nickel's lazy evaluation and recursive
|
||
|
|
merging enable powerful abstractions and
|
||
|
|
configuration composition.
|
||
|
|
</p>
|
||
|
|
<a
|
||
|
|
href="https://repo.jesusperez.pro/jesus/TypeDialog"
|
||
|
|
target="_blank"
|
||
|
|
class="repo-link"
|
||
|
|
>→ Easy config via TypeDialog</a
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="feature-box" style="border-left-color: #3b82f6">
|
||
|
|
<div class="feature-icon">🔄</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #3b82f6"
|
||
|
|
data-en="Orchestrate with Nushell"
|
||
|
|
data-es="Orquestar con Nushell"
|
||
|
|
>
|
||
|
|
Orchestrate with Nushell
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="Structured data pipelines, type-safe operations, and stateful workflows. Nushell eliminates shell script fragility while maintaining scripting simplicity."
|
||
|
|
data-es="Canales de datos estructurados, operaciones type-safe y flujos de trabajo con estado. Nushell elimina la fragilidad de los scripts de shell manteniendo la simplicidad de los scripts."
|
||
|
|
>
|
||
|
|
Structured data pipelines, type-safe operations, and
|
||
|
|
stateful workflows. Nushell eliminates shell script
|
||
|
|
fragility while maintaining scripting simplicity.
|
||
|
|
</p>
|
||
|
|
<a
|
||
|
|
href="https://repo.jesusperez.pro/jesus/nushell-plugins"
|
||
|
|
target="_blank"
|
||
|
|
class="repo-link"
|
||
|
|
style="color: #3b82f6"
|
||
|
|
>→ Nushell plugins added</a
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="feature-box" style="border-left-color: #8b5cf6">
|
||
|
|
<div class="feature-icon">⚡</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #8b5cf6"
|
||
|
|
data-en="Execute with Rust"
|
||
|
|
data-es="Ejecutar con Rust"
|
||
|
|
>
|
||
|
|
Execute with Rust
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="Performance-critical operations backed by Rust. Zero-cost abstractions, memory safety, and fearless concurrency for infrastructure tooling."
|
||
|
|
data-es="Operaciones críticas de rendimiento respaldadas por Rust. Abstracciones de costo cero, seguridad de memoria y concurrencia sin miedo para herramientas de infraestructura."
|
||
|
|
>
|
||
|
|
Performance-critical operations backed by Rust.
|
||
|
|
Zero-cost abstractions, memory safety, and fearless
|
||
|
|
concurrency for infrastructure tooling.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div class="feature-box" style="border-left-color: #f59e0b">
|
||
|
|
<div class="feature-icon">📡</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #f59e0b"
|
||
|
|
data-en="Coordinate via NATS JetStream"
|
||
|
|
data-es="Coordinar via NATS JetStream"
|
||
|
|
>
|
||
|
|
Coordinate via NATS JetStream
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="Persistent event bus for decoupled service coordination. Services exchange lease_id, task_id, and status events — credentials never traverse the bus. Auditable, replay-capable, at-least-once delivery."
|
||
|
|
data-es="Bus de eventos persistente para coordinación desacoplada. Los servicios intercambian lease_id, task_id y eventos de estado — las credenciales nunca atraviesan el bus. Auditable, con capacidad de replay y entrega at-least-once."
|
||
|
|
>
|
||
|
|
Persistent event bus for decoupled service
|
||
|
|
coordination. Services exchange lease_id, task_id,
|
||
|
|
and status events — credentials never traverse the
|
||
|
|
bus. Auditable, replay-capable, at-least-once
|
||
|
|
delivery.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div class="feature-box" style="border-left-color: #a78bfa">
|
||
|
|
<div class="feature-icon">🔐</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #a78bfa"
|
||
|
|
data-en="Secure end-to-end"
|
||
|
|
data-es="Seguridad extremo a extremo"
|
||
|
|
>
|
||
|
|
Secure end-to-end
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="Cedar policy-as-code for authorization, JWT sessions managed exclusively by ControlCenter, and post-quantum cryptography via SecretumVault. Credentials never leave the vault — services operate on lease references only."
|
||
|
|
data-es="Cedar como código de autorización, sesiones JWT gestionadas exclusivamente por ControlCenter y criptografía post-cuántica via SecretumVault. Las credenciales nunca salen del vault — los servicios operan solo con referencias de lease."
|
||
|
|
>
|
||
|
|
Cedar policy-as-code for authorization, JWT sessions
|
||
|
|
managed exclusively by ControlCenter, and
|
||
|
|
post-quantum cryptography via SecretumVault.
|
||
|
|
Credentials never leave the vault — services operate
|
||
|
|
on lease references only.
|
||
|
|
</p>
|
||
|
|
<a
|
||
|
|
href="https://repo.jesusperez.pro/jesus/secretumvault"
|
||
|
|
target="_blank"
|
||
|
|
class="repo-link"
|
||
|
|
style="color: #a78bfa"
|
||
|
|
>→ SecretumVault repo</a
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="feature-box" style="border-left-color: #ec4899">
|
||
|
|
<div class="feature-icon">🧩</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #ec4899"
|
||
|
|
data-en="Extend via OCI Registry"
|
||
|
|
data-es="Extender via OCI Registry"
|
||
|
|
>
|
||
|
|
Extend via OCI Registry
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="Distribute custom providers, task services, and cluster definitions as OCI artifacts. The Extension Registry catalogs and versions capabilities independently — swap or compose providers without touching core platform code."
|
||
|
|
data-es="Distribuye proveedores, task services y definiciones de clúster personalizados como artefactos OCI. El Extension Registry cataloga y versiona capacidades de forma independiente — intercambia o compone proveedores sin tocar el código del núcleo."
|
||
|
|
>
|
||
|
|
Distribute custom providers, task services, and
|
||
|
|
cluster definitions as OCI artifacts. The Extension
|
||
|
|
Registry catalogs and versions capabilities
|
||
|
|
independently — swap or compose providers without
|
||
|
|
touching core platform code.
|
||
|
|
</p>
|
||
|
|
<a
|
||
|
|
href="https://repo.jesusperez.pro/jesus/prvng_extensions"
|
||
|
|
target="_blank"
|
||
|
|
class="repo-link"
|
||
|
|
style="color: #ec4899"
|
||
|
|
>→ Provisioning Extensions</a
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="feature-box" style="border-left-color: #06b6d4">
|
||
|
|
<div class="feature-icon">🎛️</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #06b6d4"
|
||
|
|
data-en="Platform CLI & External Services"
|
||
|
|
data-es="CLI de Plataforma y Servicios Externos"
|
||
|
|
>
|
||
|
|
Platform CLI & External Services
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="8 platform subcommands (list, status, health, check, config, connections, init, start) with declarative external service management. Validates SurrealDB, OCI registries (Zot/Harbor), Git sources (Forgejo/Gitea), and cache before startup."
|
||
|
|
data-es="8 subcomandos de plataforma (list, status, health, check, config, connections, init, start) con gestión declarativa de servicios externos. Valida SurrealDB, registros OCI (Zot/Harbor), fuentes Git (Forgejo/Gitea) y caché antes del arranque."
|
||
|
|
>
|
||
|
|
8 platform subcommands (list, status, health, check,
|
||
|
|
config, connections, init, start) with declarative
|
||
|
|
external service management. Validates SurrealDB, OCI
|
||
|
|
registries (Zot/Harbor), Git sources (Forgejo/Gitea),
|
||
|
|
and cache before startup.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div class="feature-box" style="border-left-color: #14b8a6">
|
||
|
|
<div class="feature-icon">📌</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #14b8a6"
|
||
|
|
data-en="Centralized Version Management"
|
||
|
|
data-es="Gestión Centralizada de Versiones"
|
||
|
|
>
|
||
|
|
Centralized Version Management
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="All tool and provider versions defined in Nickel schemas. Generates bash-compatible exports via 'provisioning setup versions'. Automatic provider discovery, shell script integration, and single source of truth for Nushell, Nickel, SOPS, Age, AWS CLI, and all providers."
|
||
|
|
data-es="Todas las versiones de herramientas y proveedores definidas en esquemas Nickel. Genera exportaciones compatibles con bash via 'provisioning setup versions'. Descubrimiento automático de proveedores, integración con scripts shell y fuente única de verdad para Nushell, Nickel, SOPS, Age, AWS CLI y todos los proveedores."
|
||
|
|
>
|
||
|
|
All tool and provider versions defined in Nickel
|
||
|
|
schemas. Generates bash-compatible exports via
|
||
|
|
‘provisioning setup versions’. Automatic
|
||
|
|
provider discovery, shell script integration, and
|
||
|
|
single source of truth for Nushell, Nickel, SOPS,
|
||
|
|
Age, AWS CLI, and all providers.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<section class="section">
|
||
|
|
<h2 class="section-title">
|
||
|
|
<span
|
||
|
|
data-en="SOLID Architecture Boundaries"
|
||
|
|
data-es="Límites de Arquitectura SOLID"
|
||
|
|
>SOLID Architecture Boundaries</span
|
||
|
|
>
|
||
|
|
</h2>
|
||
|
|
<div class="features-grid">
|
||
|
|
<div class="feature-box" style="border-left-color: #ef4444">
|
||
|
|
<div class="feature-icon">🎯</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #ef4444"
|
||
|
|
data-en="Provider APIs — Orchestrator only"
|
||
|
|
data-es="APIs de Proveedor — solo Orchestrator"
|
||
|
|
>
|
||
|
|
Provider APIs — Orchestrator only
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="All hcloud, AWS, and provider SDK calls are isolated to the Orchestrator crate. Every other service routes through the Orchestrator HTTP API. SSH operations share this same boundary."
|
||
|
|
data-es="Todas las llamadas a hcloud, AWS y SDKs de proveedor están aisladas en el crate Orchestrator. Todos los demás servicios enrutan a través de la API HTTP del Orchestrator. Las operaciones SSH comparten este mismo límite."
|
||
|
|
>
|
||
|
|
All hcloud, AWS, and provider SDK calls are isolated
|
||
|
|
to the Orchestrator crate. Every other service routes
|
||
|
|
through the Orchestrator HTTP API. SSH operations
|
||
|
|
share this same boundary.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div class="feature-box" style="border-left-color: #ec4899">
|
||
|
|
<div class="feature-icon">🔐</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #ec4899"
|
||
|
|
data-en="Auth decisions — ControlCenter only"
|
||
|
|
data-es="Decisiones de Auth — solo ControlCenter"
|
||
|
|
>
|
||
|
|
Auth decisions — ControlCenter only
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="JWT validation and Cedar policy evaluation happen exclusively in ControlCenter. Other services receive a UserContext via middleware — no service re-validates tokens or evaluates policies directly."
|
||
|
|
data-es="La validación JWT y la evaluación de políticas Cedar ocurren exclusivamente en ControlCenter. Los demás servicios reciben un UserContext via middleware — ningún servicio re-valida tokens ni evalúa políticas directamente."
|
||
|
|
>
|
||
|
|
JWT validation and Cedar policy evaluation happen
|
||
|
|
exclusively in ControlCenter. Other services receive
|
||
|
|
a UserContext via middleware — no service re-validates
|
||
|
|
tokens or evaluates policies directly.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div class="feature-box" style="border-left-color: #f59e0b">
|
||
|
|
<div class="feature-icon">🔑</div>
|
||
|
|
<h3
|
||
|
|
class="feature-title"
|
||
|
|
style="color: #f59e0b"
|
||
|
|
data-en="Secrets — Vault Service API only"
|
||
|
|
data-es="Secretos — solo API del Vault Service"
|
||
|
|
>
|
||
|
|
Secrets — Vault Service API only
|
||
|
|
</h3>
|
||
|
|
<p
|
||
|
|
class="feature-text"
|
||
|
|
data-en="Credentials are never stored in NATS messages or environment variables. Services hold a lease_id and retrieve actual secrets via HTTPS to the Vault Service. The bus carries references, not values."
|
||
|
|
data-es="Las credenciales nunca se almacenan en mensajes NATS ni variables de entorno. Los servicios mantienen un lease_id y recuperan los secretos reales vía HTTPS al Vault Service. El bus transporta referencias, no valores."
|
||
|
|
>
|
||
|
|
Credentials are never stored in NATS messages or
|
||
|
|
environment variables. Services hold a lease_id and
|
||
|
|
retrieve actual secrets via HTTPS to the Vault
|
||
|
|
Service. The bus carries references, not values.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<section class="section">
|
||
|
|
<h2 class="section-title">
|
||
|
|
<span
|
||
|
|
data-en="System Architecture"
|
||
|
|
data-es="Arquitectura del Sistema"
|
||
|
|
>System Architecture</span
|
||
|
|
>
|
||
|
|
</h2>
|
||
|
|
<div class="arch-preview">
|
||
|
|
<a href="architecture-diagram.html" class="arch-img-link">
|
||
|
|
<img
|
||
|
|
class="arch-img arch-dark"
|
||
|
|
src="arch-diag-v2.svg"
|
||
|
|
alt="Architecture Diagram"
|
||
|
|
/>
|
||
|
|
<img
|
||
|
|
class="arch-img arch-light"
|
||
|
|
src="w-arch-diag-v2.svg"
|
||
|
|
alt="Architecture Diagram"
|
||
|
|
/>
|
||
|
|
</a>
|
||
|
|
<a
|
||
|
|
href="architecture-diagram.html"
|
||
|
|
class="arch-btn"
|
||
|
|
data-en="Explore Architecture →"
|
||
|
|
data-es="Explorar Arquitectura →"
|
||
|
|
>Explore Architecture →</a
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<section class="section">
|
||
|
|
<h2 class="section-title">
|
||
|
|
<span data-en="Technology Stack" data-es="Stack Tecnológico"
|
||
|
|
>Technology Stack</span
|
||
|
|
>
|
||
|
|
</h2>
|
||
|
|
<div class="tech-stack">
|
||
|
|
<span class="tech-badge">Nickel</span>
|
||
|
|
<span class="tech-badge">Nushell 0.110</span>
|
||
|
|
<span class="tech-badge">Rust</span>
|
||
|
|
<span class="tech-badge">NATS JetStream</span>
|
||
|
|
<span class="tech-badge">SurrealDB</span>
|
||
|
|
<span class="tech-badge">Cedar</span>
|
||
|
|
<span class="tech-badge">Leptos WASM</span>
|
||
|
|
<span class="tech-badge">Kubernetes</span>
|
||
|
|
<span class="tech-badge">Docker Compose</span>
|
||
|
|
<span class="tech-badge">SOPS 3.10</span>
|
||
|
|
<span class="tech-badge">Age 1.2</span>
|
||
|
|
<span class="tech-badge">Git</span>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<section class="section">
|
||
|
|
<h2 class="section-title">
|
||
|
|
<span
|
||
|
|
data-en="Platform Services (13)"
|
||
|
|
data-es="Servicios de Plataforma (13)"
|
||
|
|
>Platform Services (13)</span
|
||
|
|
>
|
||
|
|
</h2>
|
||
|
|
<div class="components-grid">
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="Orchestrator"
|
||
|
|
data-es="Orchestrator"
|
||
|
|
>Orchestrator</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="Provider APIs + SSH boundary"
|
||
|
|
data-es="APIs de proveedor + límite SSH"
|
||
|
|
>Provider APIs + SSH boundary</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="ControlCenter"
|
||
|
|
data-es="ControlCenter"
|
||
|
|
>ControlCenter</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="Cedar auth boundary"
|
||
|
|
data-es="Límite auth Cedar"
|
||
|
|
>Cedar auth boundary</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="ControlCenter-UI"
|
||
|
|
data-es="ControlCenter-UI"
|
||
|
|
>ControlCenter-UI</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="Leptos WASM dashboard"
|
||
|
|
data-es="Dashboard Leptos WASM"
|
||
|
|
>Leptos WASM dashboard</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="MCP-Server"
|
||
|
|
data-es="MCP-Server"
|
||
|
|
>MCP-Server</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="RAG + AI tools"
|
||
|
|
data-es="RAG + Herramientas IA"
|
||
|
|
>RAG + AI tools</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="AI-Service"
|
||
|
|
data-es="AI-Service"
|
||
|
|
>AI-Service</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="LLM inference layer"
|
||
|
|
data-es="Capa inferencia LLM"
|
||
|
|
>LLM inference layer</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="Extension-Registry"
|
||
|
|
data-es="Extension-Registry"
|
||
|
|
>Extension-Registry</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="Extension catalog"
|
||
|
|
data-es="Catálogo de extensiones"
|
||
|
|
>Extension catalog</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span class="component-name"
|
||
|
|
><a
|
||
|
|
href="https://repo.jesusperez.pro/jesus/secretumvault"
|
||
|
|
target="_blank"
|
||
|
|
class="component-link"
|
||
|
|
>SecretumVault</a
|
||
|
|
></span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="PQC secrets API"
|
||
|
|
data-es="API de secretos PQC"
|
||
|
|
>PQC secrets API</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="Detector"
|
||
|
|
data-es="Detector"
|
||
|
|
>Detector</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="Event detection"
|
||
|
|
data-es="Detección de eventos"
|
||
|
|
>Event detection</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="Daemon-CLI"
|
||
|
|
data-es="Daemon-CLI"
|
||
|
|
>Daemon-CLI</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="Service lifecycle"
|
||
|
|
data-es="Ciclo de vida de servicios"
|
||
|
|
>Service lifecycle</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="Machines"
|
||
|
|
data-es="Machines"
|
||
|
|
>Machines</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="Machine management"
|
||
|
|
data-es="Gestión de máquinas"
|
||
|
|
>Machine management</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="Observability"
|
||
|
|
data-es="Observability"
|
||
|
|
>Observability</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="Prometheus metrics"
|
||
|
|
data-es="Métricas Prometheus"
|
||
|
|
>Prometheus metrics</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="Backup"
|
||
|
|
data-es="Backup"
|
||
|
|
>Backup</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="State backup"
|
||
|
|
data-es="Backup de estado"
|
||
|
|
>State backup</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
<div class="component-item">
|
||
|
|
<span
|
||
|
|
class="component-name"
|
||
|
|
data-en="Encrypt"
|
||
|
|
data-es="Encrypt"
|
||
|
|
>Encrypt</span
|
||
|
|
><span
|
||
|
|
class="component-role"
|
||
|
|
data-en="Key operations"
|
||
|
|
data-es="Operaciones de clave"
|
||
|
|
>Key operations</span
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<div class="cta-section">
|
||
|
|
<h2
|
||
|
|
class="cta-title"
|
||
|
|
data-en="Ready for infrastructure automation?"
|
||
|
|
data-es="¿Listo para la automatización de infraestructura?"
|
||
|
|
>
|
||
|
|
Ready for infrastructure automation?
|
||
|
|
</h2>
|
||
|
|
<p
|
||
|
|
style="
|
||
|
|
color: #94a3b8;
|
||
|
|
margin-bottom: 2rem;
|
||
|
|
font-size: 1.05rem;
|
||
|
|
"
|
||
|
|
data-en="Built with Nickel & Nushell | Rust | Type-Safe | Open Source"
|
||
|
|
data-es="Construido con Nickel y Nushell | Rust | Type-Safe | Open Source"
|
||
|
|
>
|
||
|
|
Built with Nickel & Nushell | Type-Safe | Open Source
|
||
|
|
</p>
|
||
|
|
<a
|
||
|
|
href="https://repo.jesusperez.pro/jesus/provisioning"
|
||
|
|
class="cta-button"
|
||
|
|
data-en="Explore Git Repo →"
|
||
|
|
data-es="Explorar Repo Git →"
|
||
|
|
>Explore Git Repo →</a
|
||
|
|
>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<footer>
|
||
|
|
<p
|
||
|
|
data-en="Provisioning v3.0.11"
|
||
|
|
data-es="Provisioning v3.0.11"
|
||
|
|
>
|
||
|
|
Provisioning v3.0.11
|
||
|
|
</p>
|
||
|
|
<p
|
||
|
|
data-en="Infrastructure orchestration made elegant and type-safe ✨"
|
||
|
|
data-es="Orquestación de infraestructura hecha elegante y type-safe ✨"
|
||
|
|
>
|
||
|
|
Infrastructure orchestration made elegant and type-safe ✨
|
||
|
|
</p>
|
||
|
|
<p
|
||
|
|
style="margin-top: 1rem; font-size: 0.8rem"
|
||
|
|
data-en="Configuration as Code | Multi-Platform | Cloud-Native"
|
||
|
|
data-es="Configuración como Código | Multi-Plataforma | Cloud-Native"
|
||
|
|
>
|
||
|
|
Configuration as Code | Multi-Platform | Cloud-Native
|
||
|
|
</p>
|
||
|
|
</footer>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
// Language management
|
||
|
|
const LANG_KEY = "provisioning-lang";
|
||
|
|
|
||
|
|
function getCurrentLanguage() {
|
||
|
|
return localStorage.getItem(LANG_KEY) || "en";
|
||
|
|
}
|
||
|
|
|
||
|
|
function switchLanguage(lang) {
|
||
|
|
localStorage.setItem(LANG_KEY, lang);
|
||
|
|
|
||
|
|
// Update language buttons
|
||
|
|
document.querySelectorAll(".lang-btn").forEach((btn) => {
|
||
|
|
btn.classList.remove("active");
|
||
|
|
if (btn.dataset.lang === lang) {
|
||
|
|
btn.classList.add("active");
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Update all translatable elements
|
||
|
|
document
|
||
|
|
.querySelectorAll("[data-en][data-es]")
|
||
|
|
.forEach((el) => {
|
||
|
|
const content = el.dataset[lang];
|
||
|
|
// Use innerHTML for headings that might contain <br>, textContent for others
|
||
|
|
if (
|
||
|
|
el.tagName === "H1" ||
|
||
|
|
el.tagName === "H2" ||
|
||
|
|
el.tagName === "H3"
|
||
|
|
) {
|
||
|
|
el.innerHTML = content;
|
||
|
|
} else {
|
||
|
|
el.textContent = content;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
document.documentElement.lang = lang;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Initialize language on page load
|
||
|
|
document.addEventListener("DOMContentLoaded", () => {
|
||
|
|
const currentLang = getCurrentLanguage();
|
||
|
|
switchLanguage(currentLang);
|
||
|
|
const currentTheme = getTheme();
|
||
|
|
setTheme(currentTheme);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Theme management
|
||
|
|
const THEME_KEY = "provisioning-theme";
|
||
|
|
|
||
|
|
function getTheme() {
|
||
|
|
return localStorage.getItem(THEME_KEY) || "dark";
|
||
|
|
}
|
||
|
|
|
||
|
|
function setTheme(theme) {
|
||
|
|
localStorage.setItem(THEME_KEY, theme);
|
||
|
|
const html = document.documentElement;
|
||
|
|
const icon = document.getElementById("theme-icon");
|
||
|
|
|
||
|
|
if (theme === "light") {
|
||
|
|
html.classList.add("light-mode");
|
||
|
|
icon.textContent = "☀️";
|
||
|
|
} else {
|
||
|
|
html.classList.remove("light-mode");
|
||
|
|
icon.textContent = "🌙";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function toggleTheme() {
|
||
|
|
const currentTheme = getTheme();
|
||
|
|
const newTheme = currentTheme === "dark" ? "light" : "dark";
|
||
|
|
setTheme(newTheme);
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|