195 lines
6.7 KiB
Typst
195 lines
6.7 KiB
Typst
#import "/metadata.typ": *
|
||
#import "/tail/bibliography.typ": *
|
||
#import "/tail/glossary.typ": *
|
||
#import "/main/architecture/description.typ": *
|
||
|
||
#import "/resources/slides.typ": *
|
||
|
||
// Chemin racine des images — adapter selon ta structure de projet
|
||
#let img-root = "../../resources/img/ui_images/images/"
|
||
|
||
// ── Palette ───────────────────────────────────────────────────────────────────
|
||
#let c-dark = rgb("#0F172A")
|
||
#let c-teal = rgb("#0EA5E9")
|
||
#let c-text = rgb("#1E293B")
|
||
#let c-muted = rgb("#64748B")
|
||
#let c-white = rgb("#FFFFFF")
|
||
#let c-border = rgb("#E2E8F0")
|
||
|
||
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||
|
||
#let icon-circle(img-path, size: 38pt, bg: rgb("#0EA5E9")) = {
|
||
box(
|
||
width: size, height: size,
|
||
fill: bg, radius: (size / 2),
|
||
inset: 0pt, clip: true,
|
||
)[
|
||
#align(center + horizon)[
|
||
#image(img-path, width: (size * 0.62), height: (size * 0.62), fit: "contain")
|
||
]
|
||
]
|
||
}
|
||
|
||
#let badge(label, fill: rgb("#EF4444")) = {
|
||
box(fill: fill, radius: 3pt, inset: (x: 5pt, y: 2pt))[
|
||
#text(size: 6.5pt, weight: "bold", fill: rgb("#FFFFFF"))[#label]
|
||
]
|
||
}
|
||
|
||
#let devsec-col(phase-title, items) = {
|
||
block(width: 100%)[
|
||
#block(
|
||
width: 100%, height: 28pt,
|
||
fill: c-dark,
|
||
radius: (top-left: 5pt, top-right: 5pt, bottom-left: 0pt, bottom-right: 0pt),
|
||
inset: 0pt,
|
||
)[
|
||
#pad(x: 7pt)[
|
||
#align(horizon + center)[
|
||
#text(size: 8.5pt, weight: "bold", fill: rgb("#FFFFFF"))[#phase-title]
|
||
]
|
||
]
|
||
]
|
||
#block(
|
||
width: 100%,
|
||
fill: rgb("#F1F5F9"),
|
||
radius: (top-left: 0pt, top-right: 0pt, bottom-left: 5pt, bottom-right: 5pt),
|
||
inset: 8pt,
|
||
)[
|
||
#for item in items {
|
||
grid(columns: (30pt, 1fr), gutter: 6pt,
|
||
icon-circle(item.at("icon"), size: 28pt, bg: item.at("bg", default: c-teal)),
|
||
align(left + horizon)[
|
||
#text(size: 8pt, weight: "bold", fill: c-text)[#item.at("name")]
|
||
#linebreak()
|
||
#item.at("extra", default: [])
|
||
],
|
||
)
|
||
v(5pt)
|
||
}
|
||
]
|
||
]
|
||
}
|
||
|
||
== Cycle DevSecOps
|
||
|
||
#slide[
|
||
#grid(columns: (1fr, 1fr, 1fr, 1fr), gutter: 8pt,
|
||
devsec-col("① Code & PR Gate", (
|
||
(icon: img-root + "image10.png", bg: rgb("#3178C6"), name: "TypeScript",
|
||
extra: [#text(size: 6.5pt, fill: c-muted)[tsc / ESLint]]),
|
||
(icon: img-root + "image11.png", bg: rgb("#DD0031"), name: "Angular CI",
|
||
extra: [#text(size: 6.5pt, fill: c-muted)[Build check]]),
|
||
(icon: img-root + "image19.png", bg: rgb("#1F2328"), name: "GitHub Actions",
|
||
extra: [#text(size: 6.5pt, fill: c-muted)[Coverage]]),
|
||
)),
|
||
devsec-col("② SAST · SCA", (
|
||
(icon: img-root + "image7.png", bg: rgb("#000000"), name: "SpotBugs",
|
||
extra: [#badge("BLOCKING")]),
|
||
(icon: img-root + "image13.png", bg: rgb("#1F2328"), name: "CodeQL",
|
||
extra: [#badge("BLOCKING")]),
|
||
(icon: img-root + "image14.png", bg: rgb("#F97316"), name: "Dep. Check",
|
||
extra: [#badge("NON-BLOCK", fill: rgb("#F97316"))]),
|
||
)),
|
||
devsec-col("③ DAST · Tests", (
|
||
(icon: img-root + "image15.png", bg: rgb("#00549E"), name: "OWASP ZAP",
|
||
extra: [#badge("BLOCKING")]),
|
||
(icon: img-root + "image16.png", bg: rgb("#DD0031"), name: "Karma Tests",
|
||
extra: [#badge("BLOCKING")]),
|
||
(icon: img-root + "image17.png", bg: rgb("#64748B"), name: "Runtime check",
|
||
extra: [#text(size: 6.5pt, fill: c-muted)[HTTP headers]]),
|
||
)),
|
||
devsec-col("④ Build · Deploy", (
|
||
(icon: img-root + "image18.png", bg: rgb("#0DB7ED"), name: "Docker",
|
||
extra: [#text(size: 6.5pt, fill: c-muted)[SHA-tagged]]),
|
||
(icon: img-root + "image19.png", bg: rgb("#1F2328"), name: "GHCR Push",
|
||
extra: [#text(size: 6.5pt, fill: c-muted)[main only]]),
|
||
(icon: img-root + "image17.png", bg: rgb("#10B981"), name: "SSH Deploy",
|
||
extra: [#text(size: 6.5pt, fill: c-muted)[cert-auth]]),
|
||
)),
|
||
)
|
||
|
||
#v(7pt)
|
||
|
||
#rect(width: 100%, height: 26pt, fill: c-dark, radius: 4pt, inset: 0pt)[
|
||
#pad(x: 20pt)[
|
||
#align(horizon)[
|
||
#grid(columns: (1fr, 1fr, 1fr),
|
||
align(center + horizon)[#text(size: 8pt, fill: rgb("#FFFFFF"))[🔐 #h(2pt) Shift-left security]],
|
||
align(center + horizon)[#text(size: 8pt, fill: rgb("#FFFFFF"))[🔑 #h(2pt) Zero secret in code]],
|
||
align(center + horizon)[#text(size: 8pt, fill: rgb("#FFFFFF"))[🔄 #h(2pt) Automated Deployment]],
|
||
)
|
||
]
|
||
]
|
||
]
|
||
|
||
#v(6pt)
|
||
]
|
||
|
||
|
||
// ── SLIDE 3 — Dashboard ───────────────────────────────────────────────────────
|
||
== Dashboard
|
||
|
||
#slide[
|
||
#align(center + horizon)[
|
||
#figure(
|
||
image(img-root + "image20.png", width: 100%, fit: "contain"),
|
||
caption: [Dashboard]
|
||
)
|
||
]
|
||
]
|
||
|
||
// ── SLIDE 4 — Details Page ────────────────────────────────────────────────────
|
||
== Details Page
|
||
|
||
#slide[
|
||
#align(center + horizon)[
|
||
#figure(
|
||
image(img-root + "image21.png", width: 100%, fit: "contain"),
|
||
caption: [Details page]
|
||
)
|
||
]
|
||
]
|
||
|
||
// ── SLIDE 5 — Notification ────────────────────────────────────────────────────
|
||
== Notification
|
||
|
||
#slide[
|
||
#grid(columns: (1fr, 1fr), gutter: 16pt,
|
||
// Screenshot Telegram
|
||
align(center + horizon)[
|
||
|
||
#figure(
|
||
image(img-root + "image22.png", height: 300pt, fit: "contain"),
|
||
caption: [Telegram notification]
|
||
)
|
||
],
|
||
// Carte descriptive
|
||
rect(width: 100%, radius: 6pt, stroke: 0.5pt + c-border, fill: rgb("#FFFFFF"), inset: 12pt)[
|
||
#text(size: 10pt, weight: "bold", fill: c-text)[CO₂ Alerts System]
|
||
#v(5pt)
|
||
#line(length: 100%, stroke: 0.5pt + c-border)
|
||
#v(6pt)
|
||
|
||
#let alert-row(col, level, desc) = {
|
||
grid(columns: (10pt, 52pt, 1fr), gutter: 5pt,
|
||
box(width: 8pt, height: 8pt, fill: col, radius: 4pt),
|
||
text(size: 8.5pt, weight: "bold")[#level],
|
||
text(size: 8pt, fill: c-muted)[#desc],
|
||
)
|
||
v(4pt)
|
||
}
|
||
#alert-row(rgb("#EF4444"), "Critical", "> 2000 ppm")
|
||
#alert-row(rgb("#F97316"), "Poor", "1200–1500 ppm")
|
||
#alert-row(rgb("#EAB308"), "Moderate", "1000–1200 ppm")
|
||
#alert-row(rgb("#22C55E"), "Good", "< 800 ppm")
|
||
|
||
#v(6pt)
|
||
#line(length: 100%, stroke: 0.5pt + c-border)
|
||
#v(6pt)
|
||
|
||
#v(6pt)
|
||
|
||
],
|
||
)
|
||
] |