From b7508a6fe91adf3081da35d1fec7d5eafe23c0ec Mon Sep 17 00:00:00 2001
From: Sheogorath <sheogorath@shivering-isles.com>
Date: Mon, 1 Jan 2024 19:39:00 +0100
Subject: [PATCH] docs(vale): Add linting step to documentation

---
 .vale.ini                           |  13 ++
 .vale/Google/AMPM.yml               |   9 ++
 .vale/Google/Acronyms.yml           |  64 ++++++++++
 .vale/Google/Colons.yml             |   8 ++
 .vale/Google/Contractions.yml       |  30 +++++
 .vale/Google/DateFormat.yml         |   9 ++
 .vale/Google/Ellipses.yml           |   9 ++
 .vale/Google/EmDash.yml             |  12 ++
 .vale/Google/EnDash.yml             |  13 ++
 .vale/Google/Exclamation.yml        |   9 ++
 .vale/Google/FirstPerson.yml        |  13 ++
 .vale/Google/Gender.yml             |   9 ++
 .vale/Google/GenderBias.yml         |  47 +++++++
 .vale/Google/HeadingPunctuation.yml |  13 ++
 .vale/Google/Headings.yml           |  28 +++++
 .vale/Google/Latin.yml              |  11 ++
 .vale/Google/LyHyphens.yml          |  14 +++
 .vale/Google/OptionalPlurals.yml    |  12 ++
 .vale/Google/Ordinal.yml            |   7 ++
 .vale/Google/OxfordComma.yml        |   7 ++
 .vale/Google/Parens.yml             |   7 ++
 .vale/Google/Passive.yml            | 184 ++++++++++++++++++++++++++++
 .vale/Google/Periods.yml            |   7 ++
 .vale/Google/Quotes.yml             |   7 ++
 .vale/Google/Ranges.yml             |   7 ++
 .vale/Google/Semicolons.yml         |   8 ++
 .vale/Google/Slang.yml              |  11 ++
 .vale/Google/Spacing.yml            |  10 ++
 .vale/Google/Spelling.yml           |  10 ++
 .vale/Google/Units.yml              |   8 ++
 .vale/Google/We.yml                 |  11 ++
 .vale/Google/Will.yml               |   7 ++
 .vale/Google/WordList.yml           |  81 ++++++++++++
 .vale/Google/meta.json              |   4 +
 .vale/Google/vocab.txt              |   0
 .vale/Shivering-Isles/Spelling.yml  |   5 +
 Earthfile                           |  27 ++++
 docs/.gitlab-ci.yaml                |   5 +
 docs/src/apps/keycloak.md           |   7 ++
 docs/src/components/flux.md         |   2 +-
 docs/src/concepts/README.md         |   2 +
 docs/src/concepts/gitops.md         |   2 +-
 docs/src/concepts/sre.md            |  10 +-
 docs/src/hardware/node.md           |   2 +-
 docs/src/operating_system.md        |   2 +-
 images/tools/Earthfile              |   5 +-
 46 files changed, 758 insertions(+), 10 deletions(-)
 create mode 100644 .vale.ini
 create mode 100644 .vale/Google/AMPM.yml
 create mode 100644 .vale/Google/Acronyms.yml
 create mode 100644 .vale/Google/Colons.yml
 create mode 100644 .vale/Google/Contractions.yml
 create mode 100644 .vale/Google/DateFormat.yml
 create mode 100644 .vale/Google/Ellipses.yml
 create mode 100644 .vale/Google/EmDash.yml
 create mode 100644 .vale/Google/EnDash.yml
 create mode 100644 .vale/Google/Exclamation.yml
 create mode 100644 .vale/Google/FirstPerson.yml
 create mode 100644 .vale/Google/Gender.yml
 create mode 100644 .vale/Google/GenderBias.yml
 create mode 100644 .vale/Google/HeadingPunctuation.yml
 create mode 100644 .vale/Google/Headings.yml
 create mode 100644 .vale/Google/Latin.yml
 create mode 100644 .vale/Google/LyHyphens.yml
 create mode 100644 .vale/Google/OptionalPlurals.yml
 create mode 100644 .vale/Google/Ordinal.yml
 create mode 100644 .vale/Google/OxfordComma.yml
 create mode 100644 .vale/Google/Parens.yml
 create mode 100644 .vale/Google/Passive.yml
 create mode 100644 .vale/Google/Periods.yml
 create mode 100644 .vale/Google/Quotes.yml
 create mode 100644 .vale/Google/Ranges.yml
 create mode 100644 .vale/Google/Semicolons.yml
 create mode 100644 .vale/Google/Slang.yml
 create mode 100644 .vale/Google/Spacing.yml
 create mode 100644 .vale/Google/Spelling.yml
 create mode 100644 .vale/Google/Units.yml
 create mode 100644 .vale/Google/We.yml
 create mode 100644 .vale/Google/Will.yml
 create mode 100644 .vale/Google/WordList.yml
 create mode 100644 .vale/Google/meta.json
 create mode 100644 .vale/Google/vocab.txt
 create mode 100644 .vale/Shivering-Isles/Spelling.yml
 create mode 100644 docs/src/apps/keycloak.md

diff --git a/.vale.ini b/.vale.ini
new file mode 100644
index 000000000..9e0cc2161
--- /dev/null
+++ b/.vale.ini
@@ -0,0 +1,13 @@
+StylesPath = .vale
+MinAlertLevel = suggestion
+
+Packages = Google
+
+[*.md]
+BasedOnStyles = Vale, Google, Shivering-Isles
+
+Google.Headings = NO
+Google.Quotes = warning
+Google.Spelling = NO
+Google.Units = NO
+Vale.Spelling = NO
diff --git a/.vale/Google/AMPM.yml b/.vale/Google/AMPM.yml
new file mode 100644
index 000000000..fbdc6e4f8
--- /dev/null
+++ b/.vale/Google/AMPM.yml
@@ -0,0 +1,9 @@
+extends: existence
+message: "Use 'AM' or 'PM' (preceded by a space)."
+link: 'https://developers.google.com/style/word-list'
+level: error
+nonword: true
+tokens:
+  - '\d{1,2}[AP]M'
+  - '\d{1,2} ?[ap]m'
+  - '\d{1,2} ?[aApP]\.[mM]\.'
diff --git a/.vale/Google/Acronyms.yml b/.vale/Google/Acronyms.yml
new file mode 100644
index 000000000..f41af0189
--- /dev/null
+++ b/.vale/Google/Acronyms.yml
@@ -0,0 +1,64 @@
+extends: conditional
+message: "Spell out '%s', if it's unfamiliar to the audience."
+link: 'https://developers.google.com/style/abbreviations'
+level: suggestion
+ignorecase: false
+# Ensures that the existence of 'first' implies the existence of 'second'.
+first: '\b([A-Z]{3,5})\b'
+second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)'
+# ... with the exception of these:
+exceptions:
+  - API
+  - ASP
+  - CLI
+  - CPU
+  - CSS
+  - CSV
+  - DEBUG
+  - DOM
+  - DPI
+  - FAQ
+  - GCC
+  - GDB
+  - GET
+  - GPU
+  - GTK
+  - GUI
+  - HTML
+  - HTTP
+  - HTTPS
+  - IDE
+  - JAR
+  - JSON
+  - JSX
+  - LESS
+  - LLDB
+  - NET
+  - NOTE
+  - NVDA
+  - OSS
+  - PATH
+  - PDF
+  - PHP
+  - POST
+  - RAM
+  - REPL
+  - RSA
+  - SCM
+  - SCSS
+  - SDK
+  - SQL
+  - SSH
+  - SSL
+  - SVG
+  - TBD
+  - TCP
+  - TODO
+  - URI
+  - URL
+  - USB
+  - UTF
+  - XML
+  - XSS
+  - YAML
+  - ZIP
diff --git a/.vale/Google/Colons.yml b/.vale/Google/Colons.yml
new file mode 100644
index 000000000..99363fbd4
--- /dev/null
+++ b/.vale/Google/Colons.yml
@@ -0,0 +1,8 @@
+extends: existence
+message: "'%s' should be in lowercase."
+link: 'https://developers.google.com/style/colons'
+nonword: true
+level: warning
+scope: sentence
+tokens:
+  - ':\s[A-Z]'
diff --git a/.vale/Google/Contractions.yml b/.vale/Google/Contractions.yml
new file mode 100644
index 000000000..4f6fd5d48
--- /dev/null
+++ b/.vale/Google/Contractions.yml
@@ -0,0 +1,30 @@
+extends: substitution
+message: "Use '%s' instead of '%s'."
+link: 'https://developers.google.com/style/contractions'
+level: suggestion
+ignorecase: true
+action:
+  name: replace
+swap:
+  are not: aren't
+  cannot: can't
+  could not: couldn't
+  did not: didn't
+  do not: don't
+  does not: doesn't
+  has not: hasn't
+  have not: haven't
+  how is: how's
+  is not: isn't
+  it is: it's
+  should not: shouldn't
+  that is: that's
+  they are: they're
+  was not: wasn't
+  we are: we're
+  we have: we've
+  were not: weren't
+  what is: what's
+  when is: when's
+  where is: where's
+  will not: won't
diff --git a/.vale/Google/DateFormat.yml b/.vale/Google/DateFormat.yml
new file mode 100644
index 000000000..e9d227fa1
--- /dev/null
+++ b/.vale/Google/DateFormat.yml
@@ -0,0 +1,9 @@
+extends: existence
+message: "Use 'July 31, 2016' format, not '%s'."
+link: 'https://developers.google.com/style/dates-times'
+ignorecase: true
+level: error
+nonword: true
+tokens:
+  - '\d{1,2}(?:\.|/)\d{1,2}(?:\.|/)\d{4}'
+  - '\d{1,2} (?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)|May|Jun(?:e)|Jul(?:y)|Aug(?:ust)|Sep(?:tember)?|Oct(?:ober)|Nov(?:ember)?|Dec(?:ember)?) \d{4}'
diff --git a/.vale/Google/Ellipses.yml b/.vale/Google/Ellipses.yml
new file mode 100644
index 000000000..1e070517b
--- /dev/null
+++ b/.vale/Google/Ellipses.yml
@@ -0,0 +1,9 @@
+extends: existence
+message: "In general, don't use an ellipsis."
+link: 'https://developers.google.com/style/ellipses'
+nonword: true
+level: warning
+action:
+  name: remove
+tokens:
+  - '\.\.\.'
diff --git a/.vale/Google/EmDash.yml b/.vale/Google/EmDash.yml
new file mode 100644
index 000000000..1befe72aa
--- /dev/null
+++ b/.vale/Google/EmDash.yml
@@ -0,0 +1,12 @@
+extends: existence
+message: "Don't put a space before or after a dash."
+link: 'https://developers.google.com/style/dashes'
+nonword: true
+level: error
+action:
+  name: edit
+  params:
+    - remove
+    - ' '
+tokens:
+  - '\s[—–]\s'
diff --git a/.vale/Google/EnDash.yml b/.vale/Google/EnDash.yml
new file mode 100644
index 000000000..b314dc4e9
--- /dev/null
+++ b/.vale/Google/EnDash.yml
@@ -0,0 +1,13 @@
+extends: existence
+message: "Use an em dash ('—') instead of '–'."
+link: 'https://developers.google.com/style/dashes'
+nonword: true
+level: error
+action:
+  name: edit
+  params:
+    - replace
+    - '-'
+    - '—'
+tokens:
+  - '–'
diff --git a/.vale/Google/Exclamation.yml b/.vale/Google/Exclamation.yml
new file mode 100644
index 000000000..eea5fd24b
--- /dev/null
+++ b/.vale/Google/Exclamation.yml
@@ -0,0 +1,9 @@
+extends: existence
+message: "Don't use exclamation points in text."
+link: 'https://developers.google.com/style/exclamation-points'
+nonword: true
+level: error
+action:
+  name: remove
+tokens:
+  - '\w+!(?:\s|$)'
diff --git a/.vale/Google/FirstPerson.yml b/.vale/Google/FirstPerson.yml
new file mode 100644
index 000000000..0b7b8828c
--- /dev/null
+++ b/.vale/Google/FirstPerson.yml
@@ -0,0 +1,13 @@
+extends: existence
+message: "Avoid first-person pronouns such as '%s'."
+link: 'https://developers.google.com/style/pronouns#personal-pronouns'
+ignorecase: true
+level: warning
+nonword: true
+tokens:
+  - (?:^|\s)I\s
+  - (?:^|\s)I,\s
+  - \bI'm\b
+  - \bme\b
+  - \bmy\b
+  - \bmine\b
diff --git a/.vale/Google/Gender.yml b/.vale/Google/Gender.yml
new file mode 100644
index 000000000..c8486181d
--- /dev/null
+++ b/.vale/Google/Gender.yml
@@ -0,0 +1,9 @@
+extends: existence
+message: "Don't use '%s' as a gender-neutral pronoun."
+link: 'https://developers.google.com/style/pronouns#gender-neutral-pronouns'
+level: error
+ignorecase: true
+tokens:
+  - he/she
+  - s/he
+  - \(s\)he
diff --git a/.vale/Google/GenderBias.yml b/.vale/Google/GenderBias.yml
new file mode 100644
index 000000000..9e7019086
--- /dev/null
+++ b/.vale/Google/GenderBias.yml
@@ -0,0 +1,47 @@
+extends: substitution
+message: "Consider using '%s' instead of '%s'."
+link: 'https://developers.google.com/style/inclusive-documentation'
+ignorecase: true
+level: error
+action:
+  name: replace
+swap:
+  (?:alumna|alumnus):          graduate
+  (?:alumnae|alumni):          graduates
+  air(?:m[ae]n|wom[ae]n):      pilot(s)
+  anchor(?:m[ae]n|wom[ae]n):   anchor(s)
+  authoress:                   author
+  camera(?:m[ae]n|wom[ae]n):   camera operator(s)
+  chair(?:m[ae]n|wom[ae]n):    chair(s)
+  congress(?:m[ae]n|wom[ae]n): member(s) of congress
+  door(?:m[ae]|wom[ae]n):      concierge(s)
+  draft(?:m[ae]n|wom[ae]n):    drafter(s)
+  fire(?:m[ae]n|wom[ae]n):     firefighter(s)
+  fisher(?:m[ae]n|wom[ae]n):   fisher(s)
+  fresh(?:m[ae]n|wom[ae]n):    first-year student(s)
+  garbage(?:m[ae]n|wom[ae]n):  waste collector(s)
+  lady lawyer:                 lawyer
+  ladylike:                    courteous
+  landlord:                    building manager
+  mail(?:m[ae]n|wom[ae]n):     mail carriers
+  man and wife:                husband and wife
+  man enough:                  strong enough
+  mankind:                     human kind
+  manmade:                     manufactured
+  manpower:                    personnel
+  men and girls:               men and women
+  middle(?:m[ae]n|wom[ae]n):   intermediary
+  news(?:m[ae]n|wom[ae]n):     journalist(s)
+  ombuds(?:man|woman):         ombuds
+  oneupmanship:                upstaging
+  poetess:                     poet
+  police(?:m[ae]n|wom[ae]n):   police officer(s)
+  repair(?:m[ae]n|wom[ae]n):   technician(s)
+  sales(?:m[ae]n|wom[ae]n):    salesperson or sales people
+  service(?:m[ae]n|wom[ae]n):  soldier(s)
+  steward(?:ess)?:             flight attendant
+  tribes(?:m[ae]n|wom[ae]n):   tribe member(s)
+  waitress:                    waiter
+  woman doctor:                doctor
+  woman scientist[s]?:         scientist(s)
+  work(?:m[ae]n|wom[ae]n):     worker(s)
diff --git a/.vale/Google/HeadingPunctuation.yml b/.vale/Google/HeadingPunctuation.yml
new file mode 100644
index 000000000..b538be5b4
--- /dev/null
+++ b/.vale/Google/HeadingPunctuation.yml
@@ -0,0 +1,13 @@
+extends: existence
+message: "Don't put a period at the end of a heading."
+link: 'https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings'
+nonword: true
+level: warning
+scope: heading
+action:
+  name: edit
+  params:
+    - remove
+    - '.'
+tokens:
+  - '[a-z0-9][.]\s*$'
diff --git a/.vale/Google/Headings.yml b/.vale/Google/Headings.yml
new file mode 100644
index 000000000..e34d001b7
--- /dev/null
+++ b/.vale/Google/Headings.yml
@@ -0,0 +1,28 @@
+extends: capitalization
+message: "'%s' should use sentence-style capitalization."
+link: "https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings"
+level: warning
+scope: heading
+match: $sentence
+indicators:
+  - ":"
+exceptions:
+  - Azure
+  - CLI
+  - Cosmos
+  - Docker
+  - Emmet
+  - gRPC
+  - I
+  - Kubernetes
+  - Linux
+  - macOS
+  - Marketplace
+  - MongoDB
+  - REPL
+  - Studio
+  - TypeScript
+  - URLs
+  - Visual
+  - VS
+  - Windows
diff --git a/.vale/Google/Latin.yml b/.vale/Google/Latin.yml
new file mode 100644
index 000000000..ca03b9154
--- /dev/null
+++ b/.vale/Google/Latin.yml
@@ -0,0 +1,11 @@
+extends: substitution
+message: "Use '%s' instead of '%s'."
+link: 'https://developers.google.com/style/abbreviations'
+ignorecase: true
+level: error
+nonword: true
+action:
+  name: replace
+swap:
+  '\b(?:eg|e\.g\.)(?=[\s,;])': for example
+  '\b(?:ie|i\.e\.)(?=[\s,;])': that is
diff --git a/.vale/Google/LyHyphens.yml b/.vale/Google/LyHyphens.yml
new file mode 100644
index 000000000..ac8f557a4
--- /dev/null
+++ b/.vale/Google/LyHyphens.yml
@@ -0,0 +1,14 @@
+extends: existence
+message: "'%s' doesn't need a hyphen."
+link: 'https://developers.google.com/style/hyphens'
+level: error
+ignorecase: false
+nonword: true
+action:
+  name: edit
+  params:
+    - replace
+    - '-'
+    - ' '
+tokens:
+  - '\s[^\s-]+ly-'
diff --git a/.vale/Google/OptionalPlurals.yml b/.vale/Google/OptionalPlurals.yml
new file mode 100644
index 000000000..f858ea6fe
--- /dev/null
+++ b/.vale/Google/OptionalPlurals.yml
@@ -0,0 +1,12 @@
+extends: existence
+message: "Don't use plurals in parentheses such as in '%s'."
+link: 'https://developers.google.com/style/plurals-parentheses'
+level: error
+nonword: true
+action:
+  name: edit
+  params:
+    - remove
+    - '(s)'
+tokens:
+  - '\b\w+\(s\)'
diff --git a/.vale/Google/Ordinal.yml b/.vale/Google/Ordinal.yml
new file mode 100644
index 000000000..d1ac7d27e
--- /dev/null
+++ b/.vale/Google/Ordinal.yml
@@ -0,0 +1,7 @@
+extends: existence
+message: "Spell out all ordinal numbers ('%s') in text."
+link: 'https://developers.google.com/style/numbers'
+level: error
+nonword: true
+tokens:
+  - \d+(?:st|nd|rd|th)
diff --git a/.vale/Google/OxfordComma.yml b/.vale/Google/OxfordComma.yml
new file mode 100644
index 000000000..b9ba21ebb
--- /dev/null
+++ b/.vale/Google/OxfordComma.yml
@@ -0,0 +1,7 @@
+extends: existence
+message: "Use the Oxford comma in '%s'."
+link: 'https://developers.google.com/style/commas'
+scope: sentence
+level: warning
+tokens:
+  - '(?:[^,]+,){1,}\s\w+\s(?:and|or)'
diff --git a/.vale/Google/Parens.yml b/.vale/Google/Parens.yml
new file mode 100644
index 000000000..3b8711d0c
--- /dev/null
+++ b/.vale/Google/Parens.yml
@@ -0,0 +1,7 @@
+extends: existence
+message: "Use parentheses judiciously."
+link: 'https://developers.google.com/style/parentheses'
+nonword: true
+level: suggestion
+tokens:
+  - '\(.+\)'
diff --git a/.vale/Google/Passive.yml b/.vale/Google/Passive.yml
new file mode 100644
index 000000000..3265890e5
--- /dev/null
+++ b/.vale/Google/Passive.yml
@@ -0,0 +1,184 @@
+extends: existence
+link: 'https://developers.google.com/style/voice'
+message: "In general, use active voice instead of passive voice ('%s')."
+ignorecase: true
+level: suggestion
+raw:
+  - \b(am|are|were|being|is|been|was|be)\b\s*
+tokens:
+  - '[\w]+ed'
+  - awoken
+  - beat
+  - become
+  - been
+  - begun
+  - bent
+  - beset
+  - bet
+  - bid
+  - bidden
+  - bitten
+  - bled
+  - blown
+  - born
+  - bought
+  - bound
+  - bred
+  - broadcast
+  - broken
+  - brought
+  - built
+  - burnt
+  - burst
+  - cast
+  - caught
+  - chosen
+  - clung
+  - come
+  - cost
+  - crept
+  - cut
+  - dealt
+  - dived
+  - done
+  - drawn
+  - dreamt
+  - driven
+  - drunk
+  - dug
+  - eaten
+  - fallen
+  - fed
+  - felt
+  - fit
+  - fled
+  - flown
+  - flung
+  - forbidden
+  - foregone
+  - forgiven
+  - forgotten
+  - forsaken
+  - fought
+  - found
+  - frozen
+  - given
+  - gone
+  - gotten
+  - ground
+  - grown
+  - heard
+  - held
+  - hidden
+  - hit
+  - hung
+  - hurt
+  - kept
+  - knelt
+  - knit
+  - known
+  - laid
+  - lain
+  - leapt
+  - learnt
+  - led
+  - left
+  - lent
+  - let
+  - lighted
+  - lost
+  - made
+  - meant
+  - met
+  - misspelt
+  - mistaken
+  - mown
+  - overcome
+  - overdone
+  - overtaken
+  - overthrown
+  - paid
+  - pled
+  - proven
+  - put
+  - quit
+  - read
+  - rid
+  - ridden
+  - risen
+  - run
+  - rung
+  - said
+  - sat
+  - sawn
+  - seen
+  - sent
+  - set
+  - sewn
+  - shaken
+  - shaven
+  - shed
+  - shod
+  - shone
+  - shorn
+  - shot
+  - shown
+  - shrunk
+  - shut
+  - slain
+  - slept
+  - slid
+  - slit
+  - slung
+  - smitten
+  - sold
+  - sought
+  - sown
+  - sped
+  - spent
+  - spilt
+  - spit
+  - split
+  - spoken
+  - spread
+  - sprung
+  - spun
+  - stolen
+  - stood
+  - stridden
+  - striven
+  - struck
+  - strung
+  - stuck
+  - stung
+  - stunk
+  - sung
+  - sunk
+  - swept
+  - swollen
+  - sworn
+  - swum
+  - swung
+  - taken
+  - taught
+  - thought
+  - thrived
+  - thrown
+  - thrust
+  - told
+  - torn
+  - trodden
+  - understood
+  - upheld
+  - upset
+  - wed
+  - wept
+  - withheld
+  - withstood
+  - woken
+  - won
+  - worn
+  - wound
+  - woven
+  - written
+  - wrung
diff --git a/.vale/Google/Periods.yml b/.vale/Google/Periods.yml
new file mode 100644
index 000000000..d24a6a6c0
--- /dev/null
+++ b/.vale/Google/Periods.yml
@@ -0,0 +1,7 @@
+extends: existence
+message: "Don't use periods with acronyms or initialisms such as '%s'."
+link: 'https://developers.google.com/style/abbreviations'
+level: error
+nonword: true
+tokens:
+  - '\b(?:[A-Z]\.){3,}'
diff --git a/.vale/Google/Quotes.yml b/.vale/Google/Quotes.yml
new file mode 100644
index 000000000..3cb6f1abd
--- /dev/null
+++ b/.vale/Google/Quotes.yml
@@ -0,0 +1,7 @@
+extends: existence
+message: "Commas and periods go inside quotation marks."
+link: 'https://developers.google.com/style/quotation-marks'
+level: error
+nonword: true
+tokens:
+  - '"[^"]+"[.,?]'
diff --git a/.vale/Google/Ranges.yml b/.vale/Google/Ranges.yml
new file mode 100644
index 000000000..3ec045e77
--- /dev/null
+++ b/.vale/Google/Ranges.yml
@@ -0,0 +1,7 @@
+extends: existence
+message: "Don't add words such as 'from' or 'between' to describe a range of numbers."
+link: 'https://developers.google.com/style/hyphens'
+nonword: true
+level: warning
+tokens:
+  - '(?:from|between)\s\d+\s?-\s?\d+'
diff --git a/.vale/Google/Semicolons.yml b/.vale/Google/Semicolons.yml
new file mode 100644
index 000000000..bb8b85b42
--- /dev/null
+++ b/.vale/Google/Semicolons.yml
@@ -0,0 +1,8 @@
+extends: existence
+message: "Use semicolons judiciously."
+link: 'https://developers.google.com/style/semicolons'
+nonword: true
+scope: sentence
+level: suggestion
+tokens:
+  - ';'
diff --git a/.vale/Google/Slang.yml b/.vale/Google/Slang.yml
new file mode 100644
index 000000000..63f4c248a
--- /dev/null
+++ b/.vale/Google/Slang.yml
@@ -0,0 +1,11 @@
+extends: existence
+message: "Don't use internet slang abbreviations such as '%s'."
+link: 'https://developers.google.com/style/abbreviations'
+ignorecase: true
+level: error
+tokens:
+  - 'tl;dr'
+  - ymmv
+  - rtfm
+  - imo
+  - fwiw
diff --git a/.vale/Google/Spacing.yml b/.vale/Google/Spacing.yml
new file mode 100644
index 000000000..66e45a6b7
--- /dev/null
+++ b/.vale/Google/Spacing.yml
@@ -0,0 +1,10 @@
+extends: existence
+message: "'%s' should have one space."
+link: 'https://developers.google.com/style/sentence-spacing'
+level: error
+nonword: true
+action:
+  name: remove
+tokens:
+  - '[a-z][.?!] {2,}[A-Z]'
+  - '[a-z][.?!][A-Z]'
diff --git a/.vale/Google/Spelling.yml b/.vale/Google/Spelling.yml
new file mode 100644
index 000000000..527ac07d3
--- /dev/null
+++ b/.vale/Google/Spelling.yml
@@ -0,0 +1,10 @@
+extends: existence
+message: "In general, use American spelling instead of '%s'."
+link: 'https://developers.google.com/style/spelling'
+ignorecase: true
+level: warning
+tokens:
+  - '(?:\w+)nised?'
+  - 'colour'
+  - 'labour'
+  - 'centre'
diff --git a/.vale/Google/Units.yml b/.vale/Google/Units.yml
new file mode 100644
index 000000000..53522ab2d
--- /dev/null
+++ b/.vale/Google/Units.yml
@@ -0,0 +1,8 @@
+extends: existence
+message: "Put a nonbreaking space between the number and the unit in '%s'."
+link: "https://developers.google.com/style/units-of-measure"
+nonword: true
+level: error
+tokens:
+  - \b\d+(?:B|kB|MB|GB|TB)
+  - \b\d+(?:ns|ms|s|min|h|d)
diff --git a/.vale/Google/We.yml b/.vale/Google/We.yml
new file mode 100644
index 000000000..c7ac7d362
--- /dev/null
+++ b/.vale/Google/We.yml
@@ -0,0 +1,11 @@
+extends: existence
+message: "Try to avoid using first-person plural like '%s'."
+link: 'https://developers.google.com/style/pronouns#personal-pronouns'
+level: warning
+ignorecase: true
+tokens:
+  - we
+  - we'(?:ve|re)
+  - ours?
+  - us
+  - let's
diff --git a/.vale/Google/Will.yml b/.vale/Google/Will.yml
new file mode 100644
index 000000000..128a91836
--- /dev/null
+++ b/.vale/Google/Will.yml
@@ -0,0 +1,7 @@
+extends: existence
+message: "Avoid using '%s'."
+link: 'https://developers.google.com/style/tense'
+ignorecase: true
+level: warning
+tokens:
+  - will
diff --git a/.vale/Google/WordList.yml b/.vale/Google/WordList.yml
new file mode 100644
index 000000000..0d675f237
--- /dev/null
+++ b/.vale/Google/WordList.yml
@@ -0,0 +1,81 @@
+extends: substitution
+message: "Use '%s' instead of '%s'."
+link: "https://developers.google.com/style/word-list"
+level: warning
+ignorecase: false
+action:
+  name: replace
+swap:
+  "(?:API Console|dev|developer) key": API key
+  "(?:cell ?phone|smart ?phone)": phone|mobile phone
+  "(?:dev|developer|APIs) console": API console
+  "(?:e-mail|Email|E-mail)": email
+  "(?:file ?path|path ?name)": path
+  "(?:kill|terminate|abort)": stop|exit|cancel|end
+  "(?:OAuth ?2|Oauth)": OAuth 2.0
+  "(?:ok|Okay)": OK|okay
+  "(?:WiFi|wifi)": Wi-Fi
+  '[\.]+apk': APK
+  '3\-D': 3D
+  'Google (?:I\-O|IO)': Google I/O
+  "tap (?:&|and) hold": touch & hold
+  "un(?:check|select)": clear
+  above: preceding
+  account name: username
+  action bar: app bar
+  admin: administrator
+  Ajax: AJAX
+  a\.k\.a|aka: or|also known as
+  Android device: Android-powered device
+  android: Android
+  API explorer: APIs Explorer
+  application: app
+  approx\.: approximately
+  authN: authentication
+  authZ: authorization
+  autoupdate: automatically update
+  cellular data: mobile data
+  cellular network: mobile network
+  chapter: documents|pages|sections
+  check box: checkbox
+  check: select
+  CLI: command-line tool
+  click on: click|click in
+  Cloud: Google Cloud Platform|GCP
+  Container Engine: Kubernetes Engine
+  content type: media type
+  curated roles: predefined roles
+  data are: data is
+  Developers Console: Google API Console|API Console
+  disabled?: turn off|off
+  ephemeral IP address: ephemeral external IP address
+  fewer data: less data
+  file name: filename
+  firewalls: firewall rules
+  functionality: capability|feature
+  Google account: Google Account
+  Google accounts: Google Accounts
+  Googling: search with Google
+  grayed-out: unavailable
+  HTTPs: HTTPS
+  in order to: to
+  ingest: import|load
+  k8s: Kubernetes
+  long press: touch & hold
+  network IP address: internal IP address
+  omnibox: address bar
+  open-source: open source
+  overview screen: recents screen
+  regex: regular expression
+  SHA1: SHA-1|HAS-SHA1
+  sign into: sign in to
+  sign-?on: single sign-on
+  static IP address: static external IP address
+  stylesheet: style sheet
+  synch: sync
+  tablename: table name
+  tablet: device
+  touch: tap
+  url: URL
+  vs\.: versus
+  World Wide Web: web
diff --git a/.vale/Google/meta.json b/.vale/Google/meta.json
new file mode 100644
index 000000000..a5da2a848
--- /dev/null
+++ b/.vale/Google/meta.json
@@ -0,0 +1,4 @@
+{
+  "feed": "https://github.com/errata-ai/Google/releases.atom",
+  "vale_version": ">=1.0.0"
+}
diff --git a/.vale/Google/vocab.txt b/.vale/Google/vocab.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/.vale/Shivering-Isles/Spelling.yml b/.vale/Shivering-Isles/Spelling.yml
new file mode 100644
index 000000000..66b1bfa2b
--- /dev/null
+++ b/.vale/Shivering-Isles/Spelling.yml
@@ -0,0 +1,5 @@
+extends: spelling
+message: "'%s' is a typo!"
+dicpath: /usr/share/hunspell/
+dictionaries:
+  - en_GB
\ No newline at end of file
diff --git a/Earthfile b/Earthfile
index 7c5e0b1df..db375d61b 100644
--- a/Earthfile
+++ b/Earthfile
@@ -44,6 +44,24 @@ enable-autoupdates:
     ARG --required node
     RUN kubectl label node "${node}" upgrade.shivering-isles.com/fedora-autoupdate=true
 
+# vale-lint runs vale linting on documentation
+vale-lint:
+    FROM ./images/tools+vale
+    RUN apk add --no-cache hunspell-en
+    WORKDIR /src
+    COPY .vale.ini .vale /src/
+    COPY . /src
+    ARG alertlevel=suggestion
+    RUN vale --minAlertLevel=$alertlevel ./docs
+
+# vale-sync runs a new vale sync locally
+vale-sync:
+    FROM ./images/tools+vale
+    WORKDIR /src
+    COPY .vale.ini /src
+    RUN vale sync
+    SAVE ARTIFACT ./.vale AS LOCAL .vale
+
 # docs runs a local mdbook instance using koolbox that will listen on localhost:3000
 docs:
     WAIT
@@ -51,3 +69,12 @@ docs:
     END
     LOCALLY
     RUN koolbox mdbook serve docs
+
+docs-lint:
+    BUILD +vale-lint --alertlevel=error
+
+docs-build:
+    FROM ./images/tools+mdbook
+    COPY . .
+    RUN mdbook build docs
+    SAVE ARTIFACT ./docs/book AS LOCAL ./docs/book
diff --git a/docs/.gitlab-ci.yaml b/docs/.gitlab-ci.yaml
index cd9c4187a..bf4d76844 100644
--- a/docs/.gitlab-ci.yaml
+++ b/docs/.gitlab-ci.yaml
@@ -1,6 +1,11 @@
 stages:
     - build
 
+lint-docs:
+  extends: .earthly
+  script:
+    - earthly --ci +docs-lint
+
 build-docs:
   stage: build
   image: docker.io/library/rust
diff --git a/docs/src/apps/keycloak.md b/docs/src/apps/keycloak.md
new file mode 100644
index 000000000..6b2fb6ac0
--- /dev/null
+++ b/docs/src/apps/keycloak.md
@@ -0,0 +1,7 @@
+# Keycloak
+
+In the Shivering-Isles Infrastructure Keycloak is the central identity provider. It allows users to manage their sessions and provides Multi-Factor authentication for all services.
+
+The Keycloak instance is usually referred to as "SI-Auth". The Shivering-Isles realm contains the user-base. The Keycloak system realm, called "Master,"  administrates the Shivering-Isles realm.
+
+While the Shivering-Isles realm is accessible over the internet, allowing easy access and authentication from everywhere in the world, the "master" realm is only accessible through the local-network administration endpoint. This reduces the risk of a take over, even if an attacker compromises credentials.
diff --git a/docs/src/components/flux.md b/docs/src/components/flux.md
index 63c524b71..d4df9c4f9 100644
--- a/docs/src/components/flux.md
+++ b/docs/src/components/flux.md
@@ -2,7 +2,7 @@
 
 FluxCD is a GitOps controller. It synchronizes the content of a Git repository with a Kubernetes Cluster and makes sure the configurations are applied.
 
-The main advantage over a push based approach such as a CI pipeline, is that a GitOps operator continously reconciles the state and and runs on fully standardised operations. This avoids temporary and custom state in that is common in CI pipelines that might become hard to reproduce once the pipeline is gone.
+The main advantage over a push based approach such as a CI pipeline, is that a GitOps operator continously reconciles the state and runs on fully standardised operations. This avoids temporary and custom state in that is common in CI pipelines that might become hard to reproduce once the pipeline is gone.
 
 Links
 ---
diff --git a/docs/src/concepts/README.md b/docs/src/concepts/README.md
index 74d42e13c..8cef1b7a7 100644
--- a/docs/src/concepts/README.md
+++ b/docs/src/concepts/README.md
@@ -1 +1,3 @@
 # Concepts
+
+Just a short section to explain some concepts and their adoption in the Shivering-Isles Infrastructure. The goal is write original documentation for the Shivering-Isles infrastructure instead of copying existing content. The Shivering-Isles documentation links to upstream documentation instead.
\ No newline at end of file
diff --git a/docs/src/concepts/gitops.md b/docs/src/concepts/gitops.md
index a3a47f8e0..294cb8deb 100644
--- a/docs/src/concepts/gitops.md
+++ b/docs/src/concepts/gitops.md
@@ -1,5 +1,5 @@
 # GitOps
 
-The Shivering-Isles Infrastructure uses GitOps as central concept to maintain the Kubernetes cluster and deploy changes to production. Centralising around git as Single Source of Truth without dynmaic state provides an easier way to verify changes. It also reduces the amount of trust put into the CI system by enforcing signed commits on the GitOps operator side.
+The Shivering-Isles Infrastructure uses GitOps as central concept to maintain the Kubernetes cluster and deploy changes to production. Centralising around git as Single Source of Truth without dynamic state provides an easier way to verify changes. It also reduces the amount of trust put into the CI system by enforcing signed commits on the GitOps operator side.
 
 The current tool of choice to implement GitOps in the Shivering-Isles Infrastructure is [FluxCD](https://fluxcd.io/) in combination with a monorepo.
\ No newline at end of file
diff --git a/docs/src/concepts/sre.md b/docs/src/concepts/sre.md
index 672b1d7ed..7ce6bfe42 100644
--- a/docs/src/concepts/sre.md
+++ b/docs/src/concepts/sre.md
@@ -1,14 +1,14 @@
-# Site reliability engineering
+# Site Reliability Engineering
 
 > Site reliability engineering (SRE) is a set of principles and practices that  applies aspects of software engineering to IT infrastructure and operations.
 >
 > — [Wikipedia](https://en.wikipedia.org/w/index.php?title=Site_reliability_engineering&oldid=1191456683)
 
-In the Shivering-Isles Infrastructure various apps have an own set of SLOs to validate for service degration on changes. It's also a good pratice for SRE in other environments.
+In the Shivering-Isles Infrastructure various apps have an own set of SLOs to validate for service degradation on changes. It's also a good practice for SRE in other environments.
 
-Besides maintaining reasonable SLOs, other SRE practices are implemented, such as post mortems and especially the practice of reducing toil. All components of the infrastructure have a maintence budget, if it's depleted, it's time to fix the apps or get rid of it.
+Besides maintaining reasonable SLOs, other SRE practices are implemented, such as post mortems and especially the practice of reducing toil. All components of the infrastructure have a maintenance budget, if it's depleted, it's time to fix the apps or get rid of it.
 
-Learing about SRE
+Learning about SRE
 ---
 
 A good start is this small video Series by Google:
@@ -16,4 +16,4 @@ A good start is this small video Series by Google:
 <iframe width="100%" height="480" src="https://www.youtube-nocookie.com/embed/?listType=playlist&list=PLIivdWyY5sqJrKl7D2u-gmis8h9K66qoj" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
 
 
-Further there is the [Google SRE book](https://sre.google/sre-book/introduction/), which I can highly recommend.
\ No newline at end of file
+Further there is the [Google SRE book](https://sre.google/sre-book/introduction/) as recommended read.
\ No newline at end of file
diff --git a/docs/src/hardware/node.md b/docs/src/hardware/node.md
index 9e435c679..9fd326368 100644
--- a/docs/src/hardware/node.md
+++ b/docs/src/hardware/node.md
@@ -16,7 +16,7 @@ In order to setup the device, install the additional RAM in the underside of the
 
 <iframe width="100%" height="480" src="https://www.youtube-nocookie.com/embed/M1EL8yYe_0s?start=292" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
 
-[Hardware Maintaince Guide](https://download.lenovo.com/pccbbs/thinkcentre_pdf/m75q_gen2_hmm.pdf)
+[Hardware Maintaince Guide](https://web.archive.org/web/20230208212643/https://download.lenovo.com/pccbbs/thinkcentre_pdf/m75q_gen2_hmm.pdf)
 
 ## Power usage
 
diff --git a/docs/src/operating_system.md b/docs/src/operating_system.md
index 06611946e..d3645de5a 100644
--- a/docs/src/operating_system.md
+++ b/docs/src/operating_system.md
@@ -1,6 +1,6 @@
 # Operating System
 
-For this setup Fedora is the Operating System of choice for multiple reasons. It provides both image-based installation methods (e.g. Fedora CoreOS) as well as package-based installation methods (e.g. Fedora Server) for many architectures and provides a modern and stable set of packages. Further it matches the developer machine OS, which helps with debugging and testing things locally before pushing them onto the deployments.
+For this setup Fedora is the Operating System of choice for multiple reasons. It provides both image-based installation methods (for example Fedora CoreOS) as well as package-based installation methods (for example Fedora Server) for many architectures and provides a modern and stable set of packages. Further it matches the developer machine OS, which helps with debugging and testing things locally before pushing them onto the deployments.
 
 ## OS requirements
 
diff --git a/images/tools/Earthfile b/images/tools/Earthfile
index 5b2c40b31..96c1a70db 100644
--- a/images/tools/Earthfile
+++ b/images/tools/Earthfile
@@ -144,4 +144,7 @@ mdbook:
 
     RUN curl -L "https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz" | tar xvzf - mdbook \
         && install -o root -g root -m 0755 mdbook /usr/local/bin/mdbook
-    SAVE ARTIFACT /usr/local/bin/mdbook ./mdbook
\ No newline at end of file
+    SAVE ARTIFACT /usr/local/bin/mdbook ./mdbook
+
+vale:
+    FROM docker.io/jdkato/vale:v2.30.0
\ No newline at end of file
-- 
GitLab