diff --git a/.asciidoctor/docinfo-footer.html b/.asciidoctor/docinfo-footer.html
new file mode 100644
index 0000000000..a43ff6f707
--- /dev/null
+++ b/.asciidoctor/docinfo-footer.html
@@ -0,0 +1,9 @@
+
diff --git a/.asciidoctor/docinfo.html b/.asciidoctor/docinfo.html
new file mode 100644
index 0000000000..88ca25519c
--- /dev/null
+++ b/.asciidoctor/docinfo.html
@@ -0,0 +1,9 @@
+
+
+
diff --git a/.asciidoctor/docs.css b/.asciidoctor/docs.css
new file mode 100644
index 0000000000..a3e929f89e
--- /dev/null
+++ b/.asciidoctor/docs.css
@@ -0,0 +1,1575 @@
+/* Red Hat Fonts */
+@font-face {
+ font-family: 'Red Hat Display';
+ src: url("https://redhatofficial.github.io/RedHatFont/RedHatDisplay/RedHatDisplayVF.woff2") format('woff2-variations');
+ font-weight: 300 900;
+ font-style: normal;
+ font-display: fallback;
+}
+@font-face {
+ font-family: 'Red Hat Display';
+ src: url("https://redhatofficial.github.io/RedHatFont/RedHatDisplay/RedHatDisplayVF-Italic.woff2") format('woff2-variations');
+ font-weight: 300 900;
+ font-style: italic;
+ font-display: fallback;
+}
+@font-face {
+ font-family: 'Red Hat Text';
+ src: url("https://redhatofficial.github.io/RedHatFont/RedHatText/RedHatTextVF.woff2") format('woff2-variations');
+ font-weight: 300 700;
+ font-style: normal;
+ font-display: fallback;
+}
+@font-face {
+ font-family: 'Red Hat Text';
+ src: url("https://redhatofficial.github.io/RedHatFont/RedHatText/RedHatTextVF-Italic.woff2") format('woff2-variations');
+ font-weight: 300 700;
+ font-style: italic;
+ font-display: fallback;
+}
+@font-face {
+ font-family: 'Red Hat Mono';
+ src: url("https://redhatofficial.github.io/RedHatFont/RedHatMono/RedHatMonoVF.woff2") format('woff2-variations');
+ font-weight: 300 700;
+ font-style: normal;
+ font-display: fallback;
+}
+@font-face {
+ font-family: 'Red Hat Mono';
+ src: url("https://redhatofficial.github.io/RedHatFont/RedHatMono/RedHatMonoVF-Italic.woff2") format('woff2-variations');
+ font-weight: 300 700;
+ font-style: italic;
+ font-display: fallback;
+}
+
+/* Positioning toc and content */
+@media screen and (min-width: 768px) {
+ body.toc2 {
+ padding-left: 400px;
+ padding-right: 0;
+ }
+}
+@media screen and (min-width: 768px) {
+ #toc.toc2 {
+ margin-top: 0 !important;
+ position: fixed;
+ width: 319px;
+ left: 0;
+ top: 0;
+ border-right: 1px solid #e7e7e9;
+ border-top-width: 0 !important;
+ border-bottom-width: 0 !important;
+ z-index: 1000;
+ padding: 1.25em 1em;
+ height: 100%;
+ overflow: auto;
+ }
+}
+
+/* Style borrowed from docs.redhat.com and adapted to the HTML structure */
+
+#toc.toc2 {
+ background:#f2f2f2;
+ justify-content:space-between;
+ margin:1rem 0 2rem;
+ padding:1rem
+}
+#toctitle {
+ font-size:1.25rem;
+ font-weight:400;
+ line-height:1.6667;
+ margin-top:0;
+ text-transform:none
+}
+#toc li {
+ margin-bottom:.25em;
+ padding-left:0;
+ list-style:none;
+}
+#toc a,
+#toc a:visited {
+ color:black;
+ display:inline-block;
+ text-decoration:none;
+}
+
+.sectlevel1 {
+ padding-left:0;
+}
+
+.sectlevel2,
+.sectlevel3,
+.sectlevel4,
+.sectlevel5 {
+ padding-left:1em;
+}
+
+h3 {
+ color:#464646;
+ font-family:var(--rh-font-family-heading,"Red Hat Display",Helvetica,Arial,sans-serif);
+ font-size:var(--rh-font-size-body-text-lg,1.125rem)
+}
+
+li {
+ display:list-item;
+ margin:0;
+ padding:0;
+ text-align:-webkit-match-parent
+}
+
+*,
+:after,
+:before,
+:after,
+:before {
+ box-sizing:border-box
+}
+img,
+object,
+svg,
+img,
+object,
+svg {
+ display:inline-block;
+ max-width:100%;
+ vertical-align:middle
+}
+hr {
+ border:0;
+ border-top:.0625rem solid #d2d2d2;
+ clear:both;
+ margin:1rem 0
+}
+a {
+ color:#06c;
+ text-decoration:underline
+}
+a:focus,
+a:hover {
+ color:#036
+}
+p {
+ margin:1.49963rem 0
+}
+li>p {
+ margin:0
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family:RedHatDisplay,Red Hat Display,Helvetica Neue,Arial,sans-serif;
+ font-weight:400;
+ margin:0 0 .625rem;
+ color:#464646;
+}
+h1 {
+ font-size:2rem;
+ margin:2rem 0
+}
+h2 {
+ font-size:2rem;
+ margin:2rem 0
+}
+h3 {
+ font-size:1.65rem;
+ font-weight:400
+}
+h4 {
+ font-size:1.5rem
+}
+h5 {
+ font-size:1.25rem
+ font-weight:400
+}
+h6 {
+ font-size:1.125rem;
+ font-weight:500;
+ line-height:1.6667
+}
+ol ::marker,
+ul ::marker {
+ font:inherit
+}
+li {
+ margin:0 0 .5em;
+ padding:0
+}
+li>p {
+ margin:.5rem 0
+}
+li>ol,
+li>ul {
+ margin:0
+}
+dl dd {
+ margin:.5rem 0 .5rem 1rem
+}
+dl dd>p {
+ margin:.5rem 0
+}
+.informaltable,
+.table-contents,
+.table-wrapper {
+ max-height:var(--rh-table--maxHeight);
+ overflow:auto
+}
+table {
+ border:0;
+ font-size:1rem;
+ line-height:1.6667;
+ /* commented out as it breaks on Safari on Mac // table-layout:fixed */
+}
+table caption {
+ color:#585858;
+ margin-bottom:.5rem;
+ margin-top:.5rem;
+ text-align:left
+}
+table td,
+table th {
+ border:0;
+ border-bottom:.0625rem solid #d2d2d2;
+ border-bottom:.0625rem solid var(--pfe-table--Border,#d2d2d2);
+ padding:.5em 1rem
+}
+table td.halign-left,
+table th.halign-left {
+ text-align:left
+}
+table td.halign-center,
+table th.halign-center,
+table td.halign-center,
+table th.halign-center {
+ text-align:center
+}
+table td.halign-right,
+table th.halign-right {
+ text-align:right
+}
+table td.valign-top,
+table th.valign-top {
+ vertical-align:top
+}
+table td.valign-middle,
+table th.valign-middle {
+ vertical-align:middle
+}
+table td.valign-bottom,
+table th.valign-bottom {
+ vertical-align:bottom
+}
+table thead td,
+table thead th {
+ background:#f5f5f5;
+ font-weight:600
+}
+rh-table table,
+rh-table.rh-table--expanded-vertically {
+ max-height:-moz-max-content;
+ max-height:max-content
+}
+pre.nowrap {
+ overflow:auto;
+ overflow-wrap:normal;
+ white-space:pre;
+ word-break:normal
+}
+.listingblock pre {
+ background:transparent
+}
+
+[class] pre code {
+ background:inherit;
+ color:inherit;
+ font-family:inherit;
+ font-size:inherit;
+ font-weight:inherit;
+ line-height:inherit;
+ padding:0
+}
+.keycap,
+kbd {
+ background-color:#eee;
+ background-image:linear-gradient(180deg,#ddd,#eee,#fff);
+ border-radius:.1875rem;
+ box-shadow:0 -.0625rem #fff,0 .0625rem 0 .1875rem #aaa;
+ font-family:RedHatMono,Red Hat Mono,Consolas,monospace;
+ font-size:90%;
+ font-weight:400;
+ margin:0 .25rem;
+ padding:.125rem .375rem
+}
+.keycap strong,
+.keycap strong {
+ font-weight:inherit
+}
+kbd.keyseq,
+kbd.keyseq {
+ background:transparent;
+ border:0;
+ box-shadow:none;
+ padding:0
+}
+kbd.keyseq kbd,
+kbd.keyseq kbd {
+ display:inline-block;
+ margin:0 .375rem
+}
+kbd.keyseq kbd:first-child,
+kbd.keyseq kbd:first-child {
+ margin-left:0
+}
+b.button {
+ font-size:90%;
+ font-weight:700;
+ padding:.1875rem
+}
+b.button:before {
+ content:"["
+}
+b.button:after {
+ content:"]"
+}
+html {
+ font-family:sans-serif;
+ -ms-text-size-adjust:100%;
+ -webkit-text-size-adjust:100%
+}
+body {
+ margin:0
+}
+audio,
+canvas,
+progress,
+video {
+ display:inline-block;
+ vertical-align:baseline
+}
+audio:not([controls]) {
+ display:none;
+ height:0
+}
+[hidden],
+template {
+ display:none
+}
+a {
+ background:transparent
+}
+a:active,
+a:hover {
+ outline:0
+}
+abbr[title] {
+ border-bottom:.0625rem dotted
+}
+dfn {
+ font-style:italic
+}
+
+mark {
+ background:#ff0;
+ color:#000
+}
+small {
+ font-size:80%
+}
+sub,
+sup {
+ font-size:75%;
+ line-height:0;
+ position:relative;
+ vertical-align:baseline
+}
+sup {
+ top:-.5em
+}
+sub {
+ bottom:-.25em
+}
+img {
+ border:0
+}
+svg:not(:root) {
+ overflow:hidden
+}
+figure {
+ margin:1em 2.5rem
+}
+hr {
+ box-sizing:content-box;
+ height:0
+}
+code,
+kbd,
+pre,
+samp {
+ font-family:monospace,monospace;
+ font-size:1em
+}
+button,
+optgroup,
+select,
+textarea,
+.rhdocsinput {
+ color:inherit;
+ font:inherit;
+ margin:0
+}
+button {
+ overflow:visible
+}
+button,
+select {
+ text-transform:none
+}
+button,
+html input[type=button],
+input[type=reset],
+input[type=submit] {
+ -moz-appearance:button;
+ appearance:button;
+ -webkit-appearance:button;
+ cursor:pointer
+}
+button[disabled],
+html input[disabled] {
+ cursor:default
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border:0;
+ padding:0
+}
+input {
+ line-height:normal
+}
+input[type=checkbox],
+input[type=radio] {
+ box-sizing:border-box;
+ padding:0
+}
+input[type=number]::-webkit-inner-spin-button,
+input[type=number]::-webkit-outer-spin-button {
+ height:auto
+}
+input[type=search] {
+ -moz-appearance:textfield;
+ appearance:textfield;
+ -webkit-appearance:textfield;
+ box-sizing:content-box
+}
+input[type=search]::-webkit-search-cancel-button,
+input[type=search]::-webkit-search-decoration {
+ -webkit-appearance:none
+}
+fieldset {
+ border:.0625rem solid silver;
+ margin:0 .125rem;
+ padding:.35em .625em .75em
+}
+legend {
+ border:0;
+ padding:0
+}
+textarea {
+ overflow:auto
+}
+optgroup {
+ font-weight:700
+}
+table {
+ border-collapse:collapse;
+ border-spacing:0
+}
+td,
+th {
+ padding:0
+}
+
+.admonitionblock>div:nth-child(2),
+.caution>div:nth-child(2),
+.important>div:nth-child(2),
+.note>div:nth-child(2),
+.tip>div:nth-child(2),
+.warning>div:nth-child(2) {
+ margin:.5rem 0
+}
+.admonitionblock>div:nth-child(2)>:first-child,
+.caution>div:nth-child(2)>:first-child,
+.important>div:nth-child(2)>:first-child,
+.note>div:nth-child(2)>:first-child,
+.tip>div:nth-child(2)>:first-child,
+.warning>div:nth-child(2)>:first-child {
+ margin-top:0
+}
+.admonitionblock>div:nth-child(2)>:last-child,
+.caution>div:nth-child(2)>:last-child,
+.important>div:nth-child(2)>:last-child,
+.note>div:nth-child(2)>:last-child,
+.tip>div:nth-child(2)>:last-child,
+.warning>div:nth-child(2)>:last-child {
+ margin-bottom:0
+}
+.listingblock+.listingblock,
+pre+pre,
+pre[class]+pre[class] {
+ margin-top:2rem
+}
+.listingblock {
+ background:#f8f8f8;
+ overflow:visible;
+ position:relative;
+ transform:translate(0);
+ z-index:0;
+ border: 1px solid grey;
+ border-radius:.1rem;
+}
+.listingblock:before {
+ background-repeat:no-repeat;
+ background-size:6.25rem 100%;
+ bottom:var(--scrollbar__height,1px);
+ content:"";
+ display:block;
+ height:7.125rem;
+ max-height:100%;
+ max-height:calc(100% - var(--scrollbar__height, 2px));
+ position:absolute;
+ right:var(--scrollbar__width,6px);
+ top:.0625rem;
+ width:4.0625rem;
+ z-index:1
+}
+
+.colist>ol {
+ counter-reset:colist;
+ list-style:none;
+ margin:1rem 0 2rem;
+ padding:0
+}
+.colist>ol>li {
+ counter-increment:colist;
+ margin:.5rem 0;
+ padding-left:1.75rem;
+ position:relative;
+}
+.colist>ol>li:before {
+ content:counter(colist);
+ left:0;
+ position:absolute;
+ top:.1875rem
+}
+.colist>ol>li:before,
+.conum {
+ background:#06c;
+ border-radius:50%;
+ color:#fff;
+ display:inline-block;
+ font-family:RedHatText,Red Hat Text,Helvetica Neue,Arial,sans-serif;
+ font-style:normal;
+ font-weight:600;
+ height:1.25rem;
+ line-height:1.35rem;
+ padding:0;
+ text-align:center;
+ top:-.125em;
+ vertical-align:middle;
+ width:1.25rem
+}
+.colist div.paragraph {
+ margin:0
+}
+
+rh-table {
+ display:block
+}
+::-webkit-scrollbar,
+:host ::-webkit-scrollbar {
+ height:.625rem;
+ width:.625rem
+}
+::-webkit-scrollbar,
+::-webkit-scrollbar-track,
+:host ::-webkit-scrollbar,
+:host ::-webkit-scrollbar-track {
+ background-color:#d6d6d6
+}
+::-webkit-scrollbar-thumb,
+:host ::-webkit-scrollbar-thumb {
+ background-color:#8e8e8e
+}
+*,
+:host * {
+ scrollbar-color:#8e8e8e #d6d6d6
+}
+p:empty,
+p:empty {
+ display:none
+}
+.book {
+ font-size: var(--rh-font-size-body-text-lg,1.125rem);
+ font-weight: var(--rh-font-weight-body-text-regular,400);
+ line-height: 1.6667;
+ padding-left: 6rem;
+ padding-right: 6rem;
+ padding-top: var(--rh-space-3xl,4rem);
+ max-width: 1400px;
+}
+
+.book[class] h1 code,
+.book[class] h2 code,
+.book[class] h3 code,
+.book[class] h4 code,
+.book[class] h5 code,
+.book[class] h6 code,
+[class] h1 code,
+[class] h2 code,
+[class] h3 code,
+[class] h4 code,
+[class] h5 code,
+[class] h6 code {
+ background:transparent;
+ border:0;
+ color:inherit;
+ font:inherit;
+ margin:0;
+ padding:0
+}
+details[class] {
+ list-style:none;
+ margin:1rem 0 3rem;
+ padding:0
+}
+
+.preamble {
+ margin:0 0 2rem
+}
+.sect1 {
+ margin:2rem 0 1rem
+}
+:host .sect1,
+cp-documentation .sect1 {
+ margin:0 0 2rem;
+ padding:.0625rem 0 0
+}
+:host(.cp-documentation--has-external-header) .sect1:first-child>h2:first-child,
+:host(.cp-documentation--has-external-header) .sect1:first-child>h3:first-child {
+ margin-top:0
+}
+.listingblock,
+.literalblock {
+ margin:1rem 0
+}
+.quoteblock,
+.verseblock {
+ border-left:.25rem solid #d2d2d2;
+ margin:1rem 0;
+ padding:1rem 1rem 1rem 2rem
+}
+.quoteblock.pullleft,
+.verseblock.pullleft {
+ float:left;
+ margin-right:3rem;
+ width:25rem
+}
+@media (min-width:768px) {
+ .quoteblock.pullleft,
+ .verseblock.pullleft {
+ margin-left:-1rem
+ }
+}
+.quoteblock.pullright,
+.verseblock.pullright {
+ float:right;
+ margin-left:3rem;
+ width:25rem
+}
+@media (min-width:768) {
+ .quoteblock.pullright,
+ .verseblock.pullright {
+ margin-right:-2rem
+ }
+}
+@media (min-width:1100px) {
+ .quoteblock.pullright,
+ .verseblock.pullright {
+ margin-right:-10rem
+ }
+}
+.quoteblock>:first-child,
+.verseblock>:first-child {
+ margin-top:0
+}
+.quoteblock .content,
+.verseblock .content {
+ font-family:RedHatText,Red Hat Text,Helvetica Neue,Arial,sans-serif;
+ font-size:1.25rem;
+ line-height:1.6667
+}
+.quoteblock .attribution,
+.verseblock .attribution {
+ font-size:.875rem;
+ font-style:italic;
+ font-weight:600;
+ line-height:1.6667;
+ text-transform:uppercase
+}
+.quoteblock .attribution .citetitle,
+.verseblock .attribution .citetitle {
+ color:#585858
+}
+.quoteblock .attribution cite,
+.verseblock .attribution cite {
+ font-size:1em
+}
+.quoteblock blockquote {
+ font-style:italic;
+ margin:0;
+ padding:0
+}
+.quoteblock blockquote .content>:first-child {
+ margin-top:0
+}
+.quoteblock blockquote .content>:first-child:before {
+ color:#e00;
+ content:"“";
+ display:block;
+ float:left;
+ font-size:2.75rem;
+ font-style:normal;
+ line-height:1.125em;
+ margin-right:.5rem
+}
+.quoteblock blockquote .content>:first-child .content>:first-child:before {
+ content:none
+}
+.imageblock {
+ margin:1rem 0
+}
+.imageblock.pullleft {
+ float:left;
+ margin-right:3rem;
+ width:25rem
+}
+@media (min-width:768px) {
+ .imageblock.pullleft {
+ margin-left:-1rem
+ }
+}
+.imageblock.pullright {
+ float:right;
+ margin-left:3rem;
+ width:25rem
+}
+@media (min-width:768) {
+ .imageblock.pullright {
+ margin-right:-2rem
+ }
+}
+@media (min-width:1100px) {
+ .imageblock.pullright {
+ margin-right:-10rem
+ }
+}
+.imageblock.interrupter {
+ margin:2rem 0
+}
+@media (min-width:768px) {
+ .imageblock.interrupter {
+ margin-left:-1rem;
+ margin-right:-2rem
+ }
+ .imageblock.interrupter .caption {
+ margin-left:1rem;
+ margin-right:2rem
+ }
+}
+@media (min-width:1100px) {
+ .imageblock.interrupter {
+ margin-right:-10rem
+ }
+ .imageblock.interrupter .caption {
+ margin-right:10rem
+ }
+}
+.imageblock.interrupter img {
+ max-width:100%
+}
+.imageblock .caption {
+ color:#585858;
+ display:block;
+ font-size:.875rem;
+ line-height:1.6667;
+ margin:.5rem 0 0
+}
+.rhdocs-footnotes {
+ border-top:.0625rem solid #d2d2d2;
+ margin:3rem 0 1rem;
+ padding:1rem 0 0
+}
+.rhdocs-footnotes>ol {
+ margin:0;
+ padding:0 0 0 1.5rem
+}
+@supports (counter-reset:footnotenum) {
+ .rhdocs-footnotes>ol {
+ counter-reset:footnotenum;
+ list-style:none;
+ padding:0
+ }
+ .rhdocs-footnotes>ol>li {
+ counter-increment:footnotenum
+ }
+ .rhdocs-footnotes>ol>li:before {
+ color:#585858;
+ content:"[" counter(footnotenum) "]";
+ display:inline-block;
+ margin-right:.25rem
+ }
+}
+#footer {
+ background:#ededed;
+ color:#151515;
+ font-size:.875rem;
+ line-height:1.6667;
+ margin:3rem 0 0;
+ padding:1rem
+}
+.center {
+ margin-left:auto;
+ margin-right:auto
+}
+.stretch {
+ width:100%
+}
+
+pre,
+pre[class] {
+ margin:0;
+ padding:1.25em 1em;
+ position:relative
+}
+code[class*=language-],
+pre[class*=language-] {
+ color:#151515;
+ -moz-tab-size:4;
+ -o-tab-size:4;
+ tab-size:4
+}
+code.language-none,
+code.language-text,
+code.language-txt,
+pre.language-none,
+pre.language-text,
+pre.language-txt {
+ color:#151515
+}
+code[class*=language-] ::-moz-selection,
+code[class*=language-]::-moz-selection,
+pre[class*=language-] ::-moz-selection,
+pre[class*=language-]::-moz-selection {
+ background:#cceae7;
+ color:#263238
+}
+code[class*=language-] ::selection,
+code[class*=language-]::selection,
+pre[class*=language-] ::selection,
+pre[class*=language-]::selection {
+ background:#cceae7;
+ color:#263238
+}
+:not(pre)>code[class*=language-] {
+ border-radius:.2em;
+ padding:.1em;
+ white-space:normal
+}
+.token.atrule {
+ color:#40199a
+}
+.token.attr-name {
+ color:#06c
+}
+.token.attr-value,
+.token.attribute {
+ color:#b300b3
+}
+.token.boolean {
+ color:#40199a
+}
+.token.builtin,
+.token.cdata,
+.token.char,
+.token.class,
+.token.class-name {
+ color:#06c
+}
+.token.comment {
+ color:#6a6e73
+}
+.token.constant {
+ color:#40199a
+}
+.token.deleted {
+ color:#c9190b
+}
+.token.doctype {
+ color:#6a6e73
+}
+.token.entity {
+ color:#c9190b
+}
+.token.function {
+ color:#40199a
+}
+.token.hexcode {
+ color:#b300b3
+}
+.token.id,
+.token.important {
+ color:#40199a;
+ font-weight:700
+}
+.token.inserted {
+ color:#06c
+}
+.token.keyword {
+ color:#40199a
+}
+.token.number {
+ color:#b300b3
+}
+.token.operator {
+ color:#06c
+}
+.token.prolog {
+ color:#6a6e73
+}
+.token.property {
+ color:#06c
+}
+.token.pseudo-class,
+.token.pseudo-element {
+ color:#b300b3
+}
+.token.punctuation,
+.token.regex {
+ color:#06c
+}
+.token.selector {
+ color:#c9190b
+}
+.token.string {
+ color:#b300b3
+}
+.token.symbol {
+ color:#40199a
+}
+.token.unit {
+ color:#b300b3
+}
+.token.url,
+.token.variable {
+ color:#c9190b
+}
+
+@media print {
+ .field code,
+ .field pre,
+ code[class*=language-],
+ pre,
+ pre[class*=language-] {
+ white-space:pre-wrap!important;
+ word-wrap:break-word!important;
+ overflow-wrap:break-word!important;
+ word-break:break-word!important
+ }
+}
+
+.book>.titlepage:not(:last-child),
+.chapter,
+section[id] {
+ padding-bottom:3.75rem
+}
+.book>.titlepage .chapter:last-child,
+.book>.titlepage section[id]:last-child,
+.chapter .chapter:last-child,
+.chapter section[id]:last-child,
+section[id] .chapter:last-child,
+section[id] section[id]:last-child {
+ margin-bottom:-3.75rem
+}
+.listingblock+section[id],
+pre+section[id] {
+ padding-top:3.75rem
+}
+.cta-link {
+ font-size:inherit
+}
+a {
+ word-wrap:break-word;
+ overflow-wrap:break-word
+}
+.caution,
+.important,
+.note,
+.tip,
+.warning {
+ padding:.8888888889em;
+ position:relative
+}
+.caution {
+ background-color:#fff4cc;
+ border-top:2px solid #dca614
+}
+.important {
+ background-color:#fff4cc;
+ border-top:2px solid #dca614
+}
+.note {
+ background-color:#e0f0ff;
+ border-top:2px solid #4394e5
+}
+.tip {
+ background-color:#e0f0ff;
+ border-top:2px solid #4394e5
+}
+.warning {
+ background-color:#fff4cc;
+ border-top:2px solid #dca614
+}
+.book>.titlepage,
+.chapter,
+section[id] {
+ padding-bottom:var(--rh-space-4xl,64px)
+}
+
+.titlepage .svg-img[data*="title_logo.svg"] {
+ margin:1.5rem 0;
+ width:15rem
+}
+.paragraph {
+ margin:1.49963rem 0
+}
+.paragraph[class] {
+ margin-bottom:1.49963rem
+}
+dd {
+ margin-bottom:2.5rem
+}
+
+.example {
+ border-left:.3125rem solid #ccc;
+ margin-bottom:2rem;
+ padding:1rem 0 1rem 1rem
+}
+
+.annotator-outer[class][class] {
+ display:none;
+ flex-direction:column;
+ flex-grow:1;
+ height:auto;
+ margin:0;
+ position:static;
+ width:auto
+}
+@media (min-width:1400px) {
+ .annotator-outer[class][class] {
+ display:flex
+ }
+}
+
+.producttitle {
+ color:#000;
+ font-size:1.25rem;
+ text-transform:uppercase
+}
+.title {
+ font-size:1rem;
+ font-style:normal;
+ font-weight:700;
+ line-height:1.6667;
+ margin:1.25rem 0 0;
+ text-transform:none
+}
+.paragraph>.title[class]+.content>:first-child,
+.paragraph>.title[class]+p,
+p.title[class]+.content>:first-child,
+p.title[class]+p {
+ margin-top:0
+}
+[class] pre .caution,
+[class] pre .important,
+[class] pre .note,
+[class] pre .tip,
+[class] pre .warning {
+ background:transparent;
+ border:0;
+ color:inherit;
+ font:inherit;
+ margin:0;
+ padding:0
+}
+[class] pre .caution:after,
+[class] pre .important:after,
+[class] pre .note:after,
+[class] pre .tip:after,
+[class] pre .warning:after {
+ content:none
+}
+[class] code.email {
+ background-color:transparent;
+ font:inherit;
+ padding:0
+}
+[class] .author {
+ margin-bottom:1.5rem
+}
+[class] .author .author {
+ margin-bottom:0
+}
+table {
+ margin:2rem 0
+}
+[class] table {
+ width:auto
+}
+table .table-contents table {
+ max-width:100%;
+ overflow:auto
+}
+rh-table table {
+ margin:0;
+ max-width:9999em;
+ overflow:visible
+}
+td,
+th {
+ border-left:0;
+ padding:.5em 1rem;
+ transition:background .25s ease-out
+}
+td.content--md[class][class],
+th.content--md[class][class] {
+ min-width:13em
+}
+td.content--lg[class][class],
+th.content--lg[class][class] {
+ min-width:20em
+}
+thead th {
+ padding-top:1.5em
+}
+caption {
+ color:currentColor;
+ color:var(--pfe-table__caption--Color,currentColor);
+ font-weight:700;
+ margin-bottom:.5rem;
+ margin-top:.5rem;
+ text-align:center
+}
+.revhistory table td,
+.revhistory table th {
+ border-color:transparent
+}
+.revhistory table td {
+ padding:.625rem .875rem
+}
+.revhistory table.simplelist {
+ margin:0
+}
+@media print {
+ #masthead {
+ display:none!important
+ }
+}
+.rh-table--is-full-screen #to-top {
+ display:none
+}
+body {
+ --rh-table--maxHeight: calc(100vh - 6.25rem) ;
+ color:#151515;
+ background-color:white;
+ font-family:var(--rh-font-family-body-text,RedHatText,"Red Hat Text","Noto Sans Arabic","Noto Sans Hebrew","Noto Sans JP","Noto Sans KR","Noto Sans Malayalam","Noto Sans SC","Noto Sans TC","Noto Sans Thai",Helvetica,Arial,sans-serif);
+ font-size:var(--rh-body-copy-lage,1.125rem);
+ line-height:1.6667;
+ -moz-tab-size:4;
+ -o-tab-size:4;
+ tab-size:4
+}
+rh-codeblock::slotted(#content) {
+ border-radius:.25rem;
+ padding:var (--rh-space-lg,16px)
+}
+rh-codeblock .screen {
+ display:grid;
+ grid-template-columns:1fr 4.375rem
+}
+rh-codeblock[class][class][class][class][class] {
+ max-width:99999em
+}
+pre {
+ border:0;
+ max-height:-moz-max-content;
+ max-height:max-content
+}
+pre,
+pre[class] {
+ margin:0;
+ padding:1.25em 1em;
+ position:relative
+}
+rh-code-block>div.codeblock__inner-wrapper>pre,
+rh-code-block>div.codeblock__inner-wrapper>pre[class] {
+ margin:0;
+ padding:0;
+ position:relative
+}
+code[class*=language-],
+pre[class*=language-] {
+ color:#151515;
+ -moz-tab-size:4;
+ -o-tab-size:4;
+ tab-size:4
+}
+code.literal {
+ background:#eee;
+ border-radius:.25rem;
+ color:#000;
+ font-size:.875rem;
+ line-height:1.6667;
+ overflow-wrap:break-word;
+ padding:.125em .5em;
+ word-break:break-word
+}
+code.literal,
+kbd,
+span.keycap {
+ font-family:RedHatMono,Red Hat Mono,Consolas,monospace
+}
+kbd,
+span.keycap {
+ background-color:#eee;
+ background-image:linear-gradient(180deg,#ddd,#eee,#fff);
+ border-radius:.1875rem;
+ box-shadow:0 -.0625rem #fff,0 .0625rem 0 .1875rem #aaa;
+ font-size:90%;
+ font-weight:400;
+ margin:0 .25rem;
+ padding:.125rem .375rem
+}
+ol,
+ul {
+ margin:1rem 0;
+ padding:0 0 0 1.5rem
+}
+._additional-resources[class][class],
+._additional-resources[class][class][id]:last-child {
+ background:#fff;
+ border:.0625rem solid #d2d2d2;
+ border-radius:.1875rem;
+ margin:2em 0 4em;
+ padding:2rem 2rem 1rem
+}
+._additional-resources[class][class] ul {
+ border:0;
+ list-style:none;
+ margin:0;
+ padding:0;
+ position:relative
+}
+._additional-resources[class][class] li {
+ border-bottom:.0625rem solid #d2d2d2;
+ box-sizing:content-box;
+ margin:0;
+ padding:1rem 1.5rem 1rem 0;
+ -moz-column-break-inside:avoid;
+ break-inside:avoid
+}
+._additional-resources[class][class] li:last-child {
+ border:0
+}
+section.section#additional_resource .additional-resources__heading,
+section.section#additional_resource .heading,
+section.section#additional_resource h1,
+section.section#additional_resource h2,
+section.section#additional_resource h3,
+section.section#additional_resource h4,
+section.section#additional_resource h5,
+section.section#additional_resource h6,
+section.section#additional_resource p.title {
+ display:block;
+ font-family:RedHatDisplay,Red Hat Display,Helvetica Neue,Arial,sans-serif;
+ font-size:1.125rem;
+ font-weight:700;
+ line-height:1.5rem;
+ margin:0 0 .5rem;
+ padding:0;
+ text-transform:uppercase
+}
+section.section:first-of-type {
+ margin-top:var(--rh-space-4xl,64px)
+}
+section.section p {
+ margin-bottom:var(--rh-space-lg,16px);
+ margin-top:0
+}
+
+
+dl {
+ display:block;
+ margin-block-end:1em;
+ margin-block-start:1em;
+ margin-inline-end:0;
+ margin-inline-start:0
+}
+.paragraph {
+ margin:1.49963rem 0
+}
+img,
+object,
+svg {
+ display:inline-block;
+ max-width:100%;
+ vertical-align:middle
+}
+.titlepage .svg-img[data*="title_logo.svg"] {
+ margin:1.5rem 0;
+ width:15rem
+}
+.book[class] .author {
+ margin-bottom:1.5rem
+}
+.book[class] .author .author {
+ margin-bottom:0
+}
+.paragraph>.title[class],
+p.title[class] {
+ font-size:1rem;
+ font-style:normal;
+ font-weight:700;
+ line-height:1.6667;
+ margin:1.25rem 0 0
+}
+.example {
+ border-left:.3125rem solid #ccc;
+ margin-bottom:2rem;
+ padding:1rem 0 1rem 1rem
+}
+code {
+ background:#eee;
+ color:#000;
+ font-family:RedHatMono,Red Hat Mono,Consolas,monospace;
+ font-size:.875rem;
+ line-height:1.6667;
+ overflow-wrap:break-word;
+ padding:.125em .5em;
+ word-break:break-word
+}
+.paragraph[class] {
+ margin-bottom:1.49963rem
+}
+.book[class] code.email {
+ background-color:transparent;
+ font:inherit;
+ padding:0
+}
+
+.producttitle {
+ color:#000;
+ font-size:1.25rem;
+ text-transform:uppercase
+}
+dl {
+ margin:1rem 0
+}
+dl dt {
+ font-weight:600;
+ margin:.5rem 0
+}
+ol ol {
+ list-style:lower-roman
+}
+.codeblock--processed pf-clipboard-copy::part(input),
+.codeblock--processed pf-clipboard-copy::part(span) {
+ display:none
+}
+.token.tag {
+ color:#c9190b
+}
+
+.admonitionblock {
+ margin-bottom:var(--rh-space-lg,1rem)
+}
+.guibutton,
+.guimenu,
+.guimenuitem {
+ font-weight:700
+}
+.guibutton {
+ font-size:90%;
+ padding:.1875rem
+}
+.guibutton:before {
+ content:"["
+}
+.guibutton:after {
+ content:"]"
+}
+.book,
+{
+ --rh-table--maxHeight: calc(100vh - 6.25rem) ;
+ color:#151515;
+ font-family:RedHatText,Red Hat Text,Helvetica Neue,Arial,sans-serif;
+ font-size:1.125rem;
+ line-height:1.6667;
+ -moz-tab-size:4;
+ -o-tab-size:4;
+ tab-size:4
+}
+pre[hidden] {
+ display:none
+}
+.listingblock {
+ background:var(--rh-color-surface-lighter,#f2f2f2);
+ margin:1rem 0;
+ overflow:visible;
+ position:relative;
+ transform:translate(0);
+ z-index:0
+}
+nopre {
+ display:block;
+ font-size:.8125rem;
+ line-height:1.42857;
+ margin:0 0 .625rem;
+ word-break:break-all;
+ word-wrap:break-word;
+ background-color:var(--rh-color-surface-lighter,#f2f2f2);
+ border:.0625rem solid #ccc;
+ border-radius:.25rem;
+ color:#333
+}
+.book pre,
+pre {
+ background:var(--rh-color-surface-lighter,#f2f2f2);
+ color:#151515;
+ font-family:RedHatMono,Red Hat Mono,Consolas,monospace;
+ font-size:.875rem;
+ line-height:1.6667;
+ overflow-wrap:normal;
+ white-space:pre;
+ word-break:normal
+}
+pre[class] {
+ line-height:1.6667;
+ overflow-x:auto
+}
+*,
+:after,
+:before {
+ box-sizing:border-box
+}
+:root {
+ --rh-space-xs:4px;
+ --rh-space-sm:6px;
+ --rh-space-md:8px;
+ --rh-space-lg:16px;
+ --rh-space-xl:24px;
+ --rh-space-2xl:32px;
+ --rh-space-3xl:48px;
+ --rh-space-4xl:64px;
+ --rh-space-5xl:80px;
+ --rh-space-6xl:96px;
+ --rh-space-7xl:128px;
+ --rh-font-size-body-text-xs:.75rem;
+ --rh-font-size-body-text-sm:.875rem;
+ --rh-font-size-body-text-md:1rem;
+ --rh-font-size-body-text-lg:1.125rem;
+ --rh-font-size-body-text-xl:1.25rem;
+ --rh-font-size-body-text-2xl:1.5rem;
+ --rh-font-size-heading-xs:1.25rem;
+ --rh-font-size-heading-sm:1.5rem;
+ --rh-font-size-heading-md:1.75rem;
+ --rh-font-size-heading-lg:2.25rem;
+ --rh-font-size-heading-xl:2.5rem;
+ --rh-font-size-heading-2xl:3rem;
+ --pfe-navigation--logo--maxWidth:200px;
+ --pfe-navigation__logo--height:40px;
+ --pfe-navigation--fade-transition-delay:.5s;
+ --pfe-navigation__nav-bar--highlight-color:var(--rh-color-brand-red-on-dark,#e00);
+ --pf-global--icon--FontSize--sm:.75rem
+}
+body,
+html {
+ font-family:Red Hat Text,sans-serif;
+ font-size:var(--rh-font-size-body-text-md,1rem);
+ line-height:var(--rh-line-height-body-text,1.5);
+}
+
+main {
+ line-height:30px
+}
+section {
+ padding-bottom:3rem;
+ padding-top:3rem
+}
+img {
+ max-width:100%
+}
+a {
+ color:var(--rh-color-interactive-blue-darker,#06c);
+ text-decoration:underline
+}
+a:hover {
+ color:var(--rh-color-interactive-blue-darkest,#004080)
+}
+
+@media (min-width:576px) {
+ .book {
+ max-width:540px
+ }
+}
+@media (min-width:768px) {
+ .book {
+ max-width:720px
+ }
+}
+@media (min-width:992px) {
+ .book {
+ max-width:1250px
+ }
+}
+section {
+ padding:0
+}
+.list-unstyled {
+ list-style:none;
+ padding-left:0
+}
+.doc-image-link {
+ display:inline-block;
+ text-decoration:none
+}
+.admonitionblock{
+ margin-bottom:var(--rh-space-lg,1rem)
+ font-size:var(--rh-font-size-body-text-md,1rem)
+}
+.admonitionblock table {
+ margin:0;
+ border:none;
+ width:fit-content
+}
+.admonitionblock td {
+ margin:0;
+ border:none;
+ display:block
+}
+.admonitionblock .title {
+ margin:0;
+ color:#002952;
+ font-weight:700
+}
+
diff --git a/.asciidoctorconfig b/.asciidoctorconfig
new file mode 100644
index 0000000000..1f0bc8b86e
--- /dev/null
+++ b/.asciidoctorconfig
@@ -0,0 +1,19 @@
+// .asciidoctorconfig
+// Specifies Asciidoctor configuration to preview files in the editor
+// See: https://intellij-asciidoc-plugin.ahus1.de/docs/users-guide/features/advanced/asciidoctorconfig-file.html
+
+// Set up attributes
+include::{asciidoctorconfigdir}/artifacts/attributes.adoc[]
+
+// Set up preview style
+:chapter-signifier: Chapter
+:docinfo: shared
+:docinfodir: {asciidoctorconfigdir}/.asciidoctor
+:doctype: book
+:sectnumlevels: 5
+:sectnums:
+:source-highlighter: coderay
+:stylesdir: {asciidoctorconfigdir}/.asciidoctor
+:stylesheet: docs.css
+:toc: left
+:toclevels: 5
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000..e826aa95e4
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,14 @@
+# .editorconfig
+# Specifies editor configuration
+# See: https://editorconfig.org/
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+max_line_length = 120
+tab_width = 2
+trim_trailing_whitespace = true
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000..a7b0a0f45d
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,28 @@
+
+
+
+
+**IMPORTANT: Do Not Merge - To be merged by Docs Team Only**
+
+**Version(s):**
+
+
+**Issue:**
+
+
+**Link to docs preview:**
+
+
+**Reviews:**
+- [ ] SME: @ mention assignee
+- [ ] QE: @ mention assignee
+- [ ] Docs review: @ mention assignee
+- [ ] Additional review: @mention assignee (by writer)
+
+
+
+
+**Additional information:**
+
+
+
diff --git a/.github/workflows/build-asciidoc.yml b/.github/workflows/build-asciidoc.yml
new file mode 100644
index 0000000000..8b81b84e5b
--- /dev/null
+++ b/.github/workflows/build-asciidoc.yml
@@ -0,0 +1,90 @@
+# Copyright (c) 2023 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+name: GitHub Pages
+
+on:
+ push:
+ branches:
+ - main
+ - rhdh-1.**
+ - 1.**.x
+ - release-1.**
+
+jobs:
+ adoc_build:
+ name: Asciidoctor Build For GH Pages
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup environment
+ run: |
+ # update
+ sudo apt-get update -y || true
+ # install
+ sudo apt-get -y -q install asciidoctor && asciidoctor --version
+ echo "GIT_BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_ENV
+
+ - name: Build guides and indexes
+ run: |
+ echo "Building branch ${{ env.GIT_BRANCH }}"
+ build/scripts/build.sh -b ${{ env.GIT_BRANCH }}
+
+ # repo must be public for this to work
+ - name: Deploy
+ uses: peaceiris/actions-gh-pages@v4
+ # if: github.ref == 'refs/heads/main'
+ with:
+ github_token: ${{ secrets.RHDH_BOT_TOKEN }}
+ publish_branch: gh-pages
+ keep_files: true
+ publish_dir: ./titles-generated
+
+ - name: Cleanup merged PR branches
+ run: |
+ PULL_URL="https://api.github.com/repos/redhat-developer/red-hat-developers-documentation-rhdh/pulls"
+ GITHUB_TOKEN="${{ secrets.RHDH_BOT_TOKEN }}"
+ git config user.name "rhdh-bot service account"
+ git config user.email "rhdh-bot@redhat.com"
+
+ git checkout gh-pages; git pull || true
+ dirs=$(find . -maxdepth 1 -name "pr-*" -type d | sed -r -e "s|^\./pr-||")
+ refs=$(cat pulls.html | grep pr- | sed -r -e "s|.+.html>pr-([0-9]+).+|\1|")
+ for d in $(echo -e "$dirs\n$refs" | sort -uV); do
+ PR="${d}"
+ echo -n "Check merge status of PR $PR ... "
+ PR_JSON=$(curl -sSL -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GITHUB_TOKEN" "$PULL_URL/$PR")
+ if [[ $(echo "$PR_JSON" | grep merged\") == *"merged\": true"* ]]; then
+ echo "merged, can delete from pulls.html and remove folder $d"
+ git rm -fr --quiet "pr-${d}" || rm -fr "pr-${d}"
+ sed -r -e "/pr-$PR\/index.html>pr-$PRpr-$PR> $GITHUB_ENV
+
+ - name: Build guides and indexes
+ run: |
+ echo "Building PR ${{ github.event.pull_request.number }}"
+ build/scripts/build.sh -b "pr-${{ github.event.number }}"
+
+ - name: Pull from origin before pushing (if possible)
+ run: |
+ /usr/bin/git pull origin gh-pages || true
+
+ # repo must be public for this to work
+ - name: Deploy
+ uses: peaceiris/actions-gh-pages@v4
+ # if: github.ref == 'refs/heads/main'
+ with:
+ github_token: ${{ secrets.RHDH_BOT_TOKEN }}
+ publish_branch: gh-pages
+ keep_files: true
+ publish_dir: ./titles-generated
+
+ - name: PR comment with doc preview, replacing existing comments with a new one each time
+ shell: bash
+ env:
+ GH_TOKEN: ${{ secrets.RHDH_BOT_TOKEN }}
+ run: |
+ PR_NUM="${{ github.event.number }}"
+ ORG_REPO="${{ github.repository_owner }}/${{ github.event.repository.name }}"
+ gh repo set-default "${ORG_REPO}"
+ # for a given PR, check for existing comments from rhdh-bot; select the last one (if more than one)
+ if [[ $(gh api "repos/${ORG_REPO}/issues/${PR_NUM}/comments" -q 'map(select(.user.login=="rhdh-bot"))|last|.id') ]]; then
+ # edit that comment:
+ gh pr comment ${PR_NUM} -R "${ORG_REPO}" --edit-last --body "Updated preview: https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/pr-${PR_NUM}/ @ $(date "+%x %X")"
+ else
+ # or create a new one:
+ gh pr comment ${PR_NUM} -R "${ORG_REPO}" --body "Preview: https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/pr-${PR_NUM}/"
+ fi
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..483e61755e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+.DS_Store
+titles/*/build
+index.html
+titles-generated/
+.vale.ini
+.vale-styles/RedHat
+.vscode
+.cache/
+.vscode/
diff --git a/.htmltest.yml b/.htmltest.yml
new file mode 100644
index 0000000000..9d386e9175
--- /dev/null
+++ b/.htmltest.yml
@@ -0,0 +1,13 @@
+---
+# .htmltest.yml
+# Defines htmltest configuration
+# See: https://github.com/wjdp/htmltest
+#
+DirectoryPath: titles-generated/main
+CheckDoctype: false
+ExternalTimeout: 30
+OutputDir: .cache/htmltest
+IgnoreDirectoryMissingTrailingSlash: true
+IgnoreSSLVerify: true
+IgnoreURLs: # List URLS that are not published, false positives, websites refusing crawlers
+ - https://docs.github.com/
diff --git a/.prettierrc.yml b/.prettierrc.yml
new file mode 100644
index 0000000000..1f786b9955
--- /dev/null
+++ b/.prettierrc.yml
@@ -0,0 +1,6 @@
+semi: false
+singleQuote: true
+tabWidth: 2
+trailingComma: es5
+options:
+ editorconfig: true
diff --git a/.sync/sync-manual-trigger.png b/.sync/sync-manual-trigger.png
new file mode 100644
index 0000000000..90654613c9
Binary files /dev/null and b/.sync/sync-manual-trigger.png differ
diff --git a/.vale-styles/DeveloperHub/Attributes.yml b/.vale-styles/DeveloperHub/Attributes.yml
new file mode 100644
index 0000000000..90120f7ff0
--- /dev/null
+++ b/.vale-styles/DeveloperHub/Attributes.yml
@@ -0,0 +1,15 @@
+---
+extends: substitution
+ignorecase: false
+level: error
+message: Use the AsciiDoc attribute '{%s}' rather than '%s'.
+nonword: true
+scope: raw
+swap:
+ '{product} Hub': product
+ product Hub: product
+ Backstage: product
+ Developer Hub: product-short
+ Hub Hub: product
+ Red Hat Developer Hub: product
+ Red Hat {product}: product
diff --git a/.vale-styles/DeveloperHub/tests/fail.adoc b/.vale-styles/DeveloperHub/tests/fail.adoc
new file mode 100644
index 0000000000..f76d3e1579
--- /dev/null
+++ b/.vale-styles/DeveloperHub/tests/fail.adoc
@@ -0,0 +1,7 @@
+Configure {product} Hub.
+Install product Hub.
+Configure Backstage.
+Install Developer Hub.
+Configure Red Hat Developer Hub Hub.
+Install Red Hat Developer Hub.
+Configure Red Hat {product}.
diff --git a/.vale-styles/DeveloperHub/tests/pass.adoc b/.vale-styles/DeveloperHub/tests/pass.adoc
new file mode 100644
index 0000000000..6548cbda9a
--- /dev/null
+++ b/.vale-styles/DeveloperHub/tests/pass.adoc
@@ -0,0 +1,4 @@
+{product}
+{product-short}
+backstage
+developer hub
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000..8415ace990
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2022 [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.adoc b/README.adoc
new file mode 100644
index 0000000000..746ac63c80
--- /dev/null
+++ b/README.adoc
@@ -0,0 +1,28 @@
+# Red Hat Developer Hub documentation
+
+This repo is the upstream mirror of https://gitlab.cee.redhat.com/red-hat-developers-documentation/rhdh
+
+Contribute to this repo and merged changes will be synced to gitlab for build with Pantheon.
+
+## Building locally
+
+. Install `asciidoctor` - see https://docs.asciidoctor.org/asciidoctor/latest/install/linux-packaging/
+. Run `build/scripts/build.sh` to generate html with images in titles-generated/ folders
+
+## Previews
+
+Commits to this repo can be seen as GH Page content here:
+
+https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/
+
+Pull requests will have a link to the generated HTML attached a comment.
+
+## Contributing
+
+Submit a pull request against this repo.
+
+
+## Plugins Reference Guide
+For Plugin configuration guide, see upstream content in https://github.com/janus-idp/backstage-plugins/tree/main/plugins
+
+TODO: transform backstage-plugins markdown content into adoc, hosted in this repo. See https://issues.redhat.com/browse/RHIDP-451 for details.
diff --git a/README.sync.adoc b/README.sync.adoc
new file mode 100644
index 0000000000..fc9bd56d55
--- /dev/null
+++ b/README.sync.adoc
@@ -0,0 +1,41 @@
+# Syncing between GitHub and GitLab
+
+
+## Upstream
+
+The upstream repo for contributions to the *Red Hat Developer Hub product documentation* is:
+
+* https://github.com/redhat-developer/red-hat-developers-documentation-rhdh
+
+
+## Downstream
+
+The downstream repo (with pantheon integration) is:
+
+https://gitlab.cee.redhat.com/red-hat-developers-documentation/rhdh
+
+Please make changes to the GitHub repo. Changes made to GitLab will be overwritten.
+
+
+## Sync configuration
+
+Sync is set up for any and all https://github.com/redhat-developer/red-hat-developers-documentation-rhdh/settings/branches[PROTECTED branches] in the upstream GitHub repo.
+
+### Repo mirror configuration
+
+Should you meed to recreate the mirror setup, here are the steps:
+
+1. delete and create a new mirror rule from the `Mirroring repositories` section under https://gitlab.cee.redhat.com/red-hat-developers-documentation/rhdh/-/settings/repository[Settings > Repository].
+
+* use the format https://bot-user@github.com/redhat-developer/rhdh-documentation-sync.git (NOTE: use the *original* repo name for redhat-developer/red-hat-developers-documentation-rhdh or sync will fail)
+
+* for the password, use the bot-user's PAT (see gitlab repo rhidp/productization/secrets for the latest or to create a new one when the current one expires)
+
+* select the option to only mirror https://github.com/redhat-developer/red-hat-developers-documentation-rhdh/settings/branches[PROTECTED branches] from the upstream repo
+
+2. apply new Personal Access Token under https://gitlab.cee.redhat.com/red-hat-developers-documentation/rhdh/-/settings/integrations/github/edit[Settings > Integrations > Github].
+
+3. You can manually trigger a sync from the `Mirroring repositories` section under https://gitlab.cee.redhat.com/red-hat-developers-documentation/rhdh/-/settings/repository[Settings > Repository].
+
+image::.sync/sync-manual-trigger.png[Repository Settings > expand Mirroring repositories > click circular arrows button]
+
diff --git a/artifacts/attributes.adoc b/artifacts/attributes.adoc
new file mode 100644
index 0000000000..aa462f3134
--- /dev/null
+++ b/artifacts/attributes.adoc
@@ -0,0 +1,105 @@
+:red-hat-developers-documentation:
+:imagesdir:
+:idseparator: -
+
+// Company names
+:company-name: Red Hat
+
+// Products
+:product-author: CCS
+:product: Red Hat Developer Hub
+:product-short: Developer Hub
+:product-very-short: RHDH
+:product-version: 1.3
+:product-bundle-version: 1.3.0
+:product-chart-version: 1.3.0
+:product-backstage-version: 1.29.2
+:rhdeveloper-name: Red Hat Developer
+:rhel: Red Hat Enterprise Linux
+:odf-name: OpenShift Data Foundation
+
+:my-product-url: https://____
+
+// Red Hat Platforms
+:ocp-brand-name: Red Hat OpenShift Container Platform
+:ocp-short: OpenShift Container Platform
+:ocp-very-short: RHOCP
+:osd-brand-name: Red Hat OpenShift Dedicated
+:osd-short: OpenShift Dedicated
+// minimum and current latest supported versions
+:ocp-version-min: 4.14
+:ocp-version: 4.16
+// First mention of OpenShift CLI or `oc` in a module
+:openshift-cli: pass:quotes[OpenShift CLI (`oc`)]
+:rhsso-brand-name: Red Hat Single-Sign On
+:rhsso: RHSSO
+
+// Partner Platforms
+:aws-brand-name: Amazon Web Services
+:aws-short: AWS
+:azure-brand-name: Microsoft Azure
+:azure-short: Azure
+:eks-brand-name: Amazon Elastic Kubernetes Service
+:eks-name: Elastic Kubernetes Service
+:eks-short: EKS
+:aks-brand-name: Microsoft Azure Kubernetes Service
+:aks-name: Azure Kubernetes Service
+:aks-short: AKS
+:gke-brand-name: Google Kubernetes Engine
+:gke-short: GKE
+:gcp-brand-name: Google Cloud Platform
+:gcp-short: GCP
+
+// Release Notes
+:rn-product-title: Release notes for Red Hat Developer Hub
+
+// Red Hat Developer Hub administration guide
+:ag-product-title: Administration guide for Red Hat Developer Hub
+
+// Red Hat Developer Hub getting started guide
+:gs-product-title: Getting started with Red Hat Developer Hub
+
+// Backstage Plugins for Red Hat Developer Hub
+//:bs-product-title: Backstage Plugins for Red Hat Developer Hub
+
+// User Guide
+:ug-product-title: Red Hat Developer Hub User Guide
+
+// Links
+:LinkAdminGuide: https://access.redhat.com/documentation/en-us/red_hat_developer_hub/{product-version}/html-single/administration_guide_for_red_hat_developer_hub/index
+:NameOfAdminGuide: Administration guide for {product}
+
+:LinkGettingStartedGuide: https://access.redhat.com/documentation/en-us/red_hat_developer_hub/{product-version}/html-single/getting_started_with_red_hat_developer_hub/index
+
+:LinkPluginsGuide: https://access.redhat.com/documentation/en-us/red_hat_developer_hub/{product-version}/html-single/configuring_plugins_in_red_hat_developer_hub/index
+:NameOfPluginsGuide: Configuring plugins in {product}
+
+:release-notes-url: https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/release_notes/index
+:release-notes-title: Release notes
+
+:installing-and-viewing-dynamic-plugins-url: https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/installing_and_viewing_dynamic_plugins/index
+:installing-and-viewing-dynamic-plugins-title: Installing and viewing dynamic plugins
+
+:authentication-book-url: https://docs.redhat.com/documentation/en-us/red_hat_developer_hub/{product-version}/html-single/authentication/index
+:authentication-book-title: Authentication
+
+:authorization-book-url: https://docs.redhat.com/documentation/en-us/red_hat_developer_hub/{product-version}/html-single/authorization/index
+:authorization-book-title: Authorization
+
+:installing-on-ocp-book-url: https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/installing_red_hat_developer_hub_on_openshift_container_platform/index
+:installing-on-ocp-book-title: Installing {product} on {ocp-short}
+
+:installing-on-eks-book-url: https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/installing_red_hat_developer_hub_on_amazon_elastic_kubernetes_service/index
+:installing-on-eks-book-title: Installing {product} on {eks-brand-name}
+
+:installing-on-aks-book-url: https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/installing_red_hat_developer_hub_on_microsoft_azure_kubernetes_service/index
+:installing-on-aks-book-title: Installing {product} on {aks-brand-name}
+
+:installing-in-air-gap-book-url: https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/installing_red_hat_developer_hub_in_an_air-gapped_environment/index
+:installing-in-air-gap-book-title: Installing {product} in an air-gapped environment
+
+:upgrading-book-url: https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/upgrading_red_hat_developer_hub/index
+:upgrading-book-title: Upgrading {product}
+
+:plugins-configure-book-url: https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/configuring_dynamic_plugins/index
+:plugins-configure-book-title: Configuring dynamic plugins
diff --git a/artifacts/rhdh-plugins-reference/aap-backend/aap-backend-install-dynamic-plugin.adoc b/artifacts/rhdh-plugins-reference/aap-backend/aap-backend-install-dynamic-plugin.adoc
new file mode 100644
index 0000000000..45352c66b8
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/aap-backend/aap-backend-install-dynamic-plugin.adoc
@@ -0,0 +1,22 @@
+.Installation
+The AAP backend plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the `disabled` property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-aap-backend-dynamic
+ disabled: false
+----
+
+.Basic configuration
+To enable the AAP plugin, you must set the following environment variables:
+
+* `AAP_BASE_URL`
+
+* `AAP AUTH TOKEN`
+
+.Advanced configuration
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/aap-backend/aap-backend-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/aap-backend/aap-backend-plugin-readme.adoc
new file mode 100644
index 0000000000..bc06dc0cf1
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/aap-backend/aap-backend-plugin-readme.adoc
@@ -0,0 +1,116 @@
+= Installation and configuration of Ansible Automation Platform
+
+The Ansible Automation Platform (AAP) plugin synchronizes the accessible templates including job templates and workflow job templates from AAP into your {product-short} catalog.
+
+[IMPORTANT]
+====
+The Ansible Automation Platform plugin is a Technology Preview feature only.
+
+Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+Additional detail on how Red Hat provides support for bundled community dynamic plugins is available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
+
+== For administrators
+
+=== Installing and configuring the AAP Backend plugin
+
+The AAP backend plugin allows you to configure one or multiple providers using your `app-config.yaml` configuration file in {product-short}.
+
+.Prerequisites
+* Your {product-short} application is installed and running.
+* You have created an account in Ansible Automation Platform.
+
+.Installation
+The AAP backend plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the `disabled` property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-aap-backend-dynamic
+ disabled: false
+----
+
+.Basic configuration
+To enable the AAP plugin, you must set the following environment variables:
+
+* `AAP_BASE_URL`: Base URL of the service
+
+* `AAP AUTH TOKEN`: Authentication token for the service
+
+.Advanced configuration
+
+. You can use the `aap` marker to configure the `app-config.yaml` file of {product-short} as follows:
++
+--
+[source,yaml]
+----
+ catalog:
+ providers:
+ aap:
+ dev:
+ baseUrl: $(AAP_BASE_URL)
+ authorization: 'Bearer ${AAP_AUTH_TOKEN}'
+ owner:
+ system:
+ schedule: # optional; same options as in TaskScheduleDefinition
+ # supports cron, ISO duration, "human duration" as used in code
+ frequency: { minutes: 1 }
+ # supports ISO duration, "human duration" as used in code
+ timeout: { minutes: 1 }
+----
+--
+
+=== Log lines for AAP Backend plugin troubleshoot
+
+When you start your {product-short} application, you can see the following log lines:
+
+[source,log]
+----
+[1] 2023-02-13T15:26:09.356Z catalog info Discovered ResourceEntity API type=plugin target=AapResourceEntityProvider:dev
+[1] 2023-02-13T15:26:09.423Z catalog info Discovered ResourceEntity Red Hat Event (DEV, v1.2.0) type=plugin target=AapResourceEntityProvider:dev
+[1] 2023-02-13T15:26:09.620Z catalog info Discovered ResourceEntity Red Hat Event (TEST, v1.1.1) type=plugin target=AapResourceEntityProvider:dev
+[1] 2023-02-13T15:26:09.819Z catalog info Discovered ResourceEntity Red Hat Event (PROD, v1.1.1) type=plugin target=AapResourceEntityProvider:dev
+[1] 2023-02-13T15:26:09.819Z catalog info Applying the mutation with 3 entities type=plugin target=AapResourceEntityProvider:dev
+----
+
+== For users
+
+=== Accessing templates from AAP in {product-short}
+
+When you have configured the AAP backend plugin successfully, it synchronizes the templates including job templates and workflow job templates from AAP and displays them on the {product-short} Catalog page as Resources.
+
+.Prerequisites
+
+* Your {product-short} application is installed and running.
+* You have installed the AAP backend plugin. For installation and configuration instructions, see <>.
+
+.Procedure
+
+. Open your {product-short} application and Go to the *Catalog* page.
+. Select *Resource* from the *Kind* drop-down and *job template* or *workflow job template* from the *Type* drop-down on the left side of the page.
++
+--
+image::rhdh-plugins-reference/aap-backend-plugin-user1.png[aap-backend-plugin-backstage]
+
+A list of all the available templates from AAP appears on the page.
+--
+
+. Select a template from the list.
++
+--
+The *OVERVIEW* tab appears containing different cards, such as:
+
+* *About*: Provides detailed information about the template.
+* *Relations*: Displays the visual representation of the template and associated aspects.
+* *Links*: Contains links to the AAP dashboard and the details page of the template.
+* *Has subcomponents*: Displays a list of associated subcomponents.
+
+image::rhdh-plugins-reference/aap-backend-plugin-user2.png[aap-backend-plugin-backstage-details]
+--
diff --git a/artifacts/rhdh-plugins-reference/acr/acr-install-dynamic-plugin.adoc b/artifacts/rhdh-plugins-reference/acr/acr-install-dynamic-plugin.adoc
new file mode 100644
index 0000000000..0a07ccf2ba
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/acr/acr-install-dynamic-plugin.adoc
@@ -0,0 +1,15 @@
+.Installation
+The ACR plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the `disabled` property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-acr
+ disabled: false
+----
+
+.Configuration
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/acr/acr-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/acr/acr-plugin-readme.adoc
new file mode 100644
index 0000000000..2f0f68c778
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/acr/acr-plugin-readme.adoc
@@ -0,0 +1,153 @@
+= Azure Container Registry
+
+The Azure Container Registry (ACR) plugin displays information about your container images available in the Azure Container Registry.
+
+[IMPORTANT]
+====
+The Azure Container Registry plugin is a Technology Preview feature only.
+
+Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+Additional detail on how Red Hat provides support for bundled community dynamic plugins is available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
+
+== For administrators
+
+=== Installing and configuring the ACR plugin
+ifeval::[{doc-show-dynamic-content} == true]
+include::../../../artifacts/rhdh-plugins-reference/acr/acr-install-dynamic-plugin.adoc[leveloffset=+2]
+endif::[]
+
+ifeval::[{doc-show-dynamic-content} == false]
+The Red Hat Plug-ins for Backstage (RHPIB) packages are hosted in a separate NPM registry, which is maintained by Red Hat. To use these packages, you must adjust your NPM configuration to pull the `@redhat` scoped packages:
+
+[source]
+----
+# update your .npmrc or .yarnrc file
+yarn config set "@redhat:registry" https://npm.registry.redhat.com
+# then pull a package
+yarn add @redhat/backstage-plugin-quay
+----
+
+For more information, see link:https://docs.npmjs.com/cli/v9/configuring-npm/npmrc[npm docs].
+
+Creating a `.npmrc` file ensures that all the packages are scoped under `@redhat` and are fetched from link:https://npm.registry.redhat.com/[Red Hat's NPM registry], while the rest dependencies remain sourced from other link:registry.npmjs.org[registry].
+
+.Procedure
+
+. Run the following command to install the ACR plugin:
++
+--
+[source]
+----
+yarn workspace app add @redhat/backstage-plugin-acr
+----
+--
+endif::[]
+
+. Set the proxy to the desired ACR server in the `app-config.yaml` file as follows:
++
+--
+[source,yaml]
+----
+ # app-config.yaml
+ proxy:
+ '/acr/api':
+ target: 'https://mycontainerregistry.azurecr.io/acr/v1/'
+ changeOrigin: true
+ headers:
+ # If you use Bearer Token for authorization, please replace the 'Basic' with 'Bearer' in the following line.
+ Authorization: 'Basic ${ACR_AUTH_TOKEN}'
+ # Change to "false" in case of using self hosted artifactory instance with a self-signed certificate
+ secure: true
+----
+--
+
+. Set the authorization using one of the following options:
++
+--
+* Basic authorization:
+** Navigate to the ACR portal and go to the *Access Keys* tab.
+** Retrieve the username and password of the Admin user and use the https://www.debugbear.com/basic-auth-header-generator[Basic Auth Header Generator tool] or run `echo printf ':' | base64` in a terminal to convert the credentials to a basic token.
+** Set the generated token as `ACR_AUTH_TOKEN` in environment variables.
+
+* OAuth2:
+
+** Generate bearer access token using the process described in Authenticate with an Azure Container Registry.
++
+You can generate a bearer token using your basic authorization token, for example:
++
+[source,curl]
+----
+curl --location 'https://.azurecr.io/oauth2/token?scope=repository%3A*%3A*&service=.azurecr.io' \ --header 'Authorization: Basic '
+----
+
+** Set the generated token as `ACR_AUTH_TOKEN` in environment variables. Also ensure that you replace the `Basic` with `Bearer` in the `app-config.yaml` file.
+--
+
+. Enable an additional tab on the entity view page using the `packages/app/src/components/catalog/EntityPage.tsx` file as follows:
++
+--
+[source]
+----
+/* highlight-add-start */
+import { AcrPage, isAcrAvailable } from '@redhat/backstage-plugin-acr';
+
+/* highlight-add-end */
+
+const serviceEntityPage = (
+
+ // ...
+ {/* highlight-add-start */}
+
+
+
+ Boolean(isAcrAvailable(e))}>
+
+
+
+
+
+
+
+ {/* highlight-add-end */}
+
+);
+----
+--
+
+. Annotate your entity using the following annotations:
++
+--
+[source,yaml]
+----
+metadata:
+ annotations:
+ 'azure-container-registry/repository-name': `',
+----
+--
+
+== For users
+
+=== Using the ACR plugin in {product-short}
+
+ACR is a front-end plugin that enables you to view information about the container images from your Azure Container Registry in {product-short}.
+
+.Prerequisites
+
+* Your {product-short} application is installed and running.
+* You have installed the ACR plugin. For installation instructions, see <>.
+
+.Procedure
+
+. Open your {product-short} application and select a component from the *Catalog* page.
+
+. Go to the *ACR* tab.
++
+--
+image::acr-plugin-user1.png[acr-tab]
+
+The *ACR* tab in the {product-short} UI contains a list of container images and related information, such as *TAG*, *CREATED*, *LAST MODIFIED*, and *MANIFEST*.
+--
diff --git a/artifacts/rhdh-plugins-reference/argocd/argocd-plugin-admin.adoc b/artifacts/rhdh-plugins-reference/argocd/argocd-plugin-admin.adoc
new file mode 100644
index 0000000000..41e5294fd0
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/argocd/argocd-plugin-admin.adoc
@@ -0,0 +1,78 @@
+= Enabling the Argo CD plugin
+
+You can use the Argo CD plugin to visualize the Continuous Delivery (CD) workflows in OpenShift GitOps. This plugin provides a visual overview of the application’s status, deployment details, commit message, author of the commit, container image promoted to environment and deployment history.
+
+.Prerequisites
+
+* Add Argo CD instance information to your `app-config.yaml` configmap as shown in the following example:
+
++
+[source,yaml]
+----
+argocd:
+ appLocatorMethods:
+ - type: 'config'
+ instances:
+ - name: argoInstance1
+ url: https://argoInstance1.com
+ username: ${ARGOCD_USERNAME}
+ password: ${ARGOCD_PASSWORD}
+ - name: argoInstance2
+ url: https://argoInstance2.com
+ username: ${ARGOCD_USERNAME}
+ password: ${ARGOCD_PASSWORD}
+----
+
+* Add the following annotation to the entity’s `catalog-info.yaml` file to identify the Argo CD applications.
+
++
+[source,yaml]
+----
+annotations:
+ ...
+ # The label that Argo CD uses to fetch all the applications. The format to be used is label.key=label.value. For example, rht-gitops.com/janus-argocd=quarkus-app.
+
+ argocd/app-selector: '${ARGOCD_LABEL_SELECTOR}'
+----
+
+* (Optional) Add the following annotation to the entity’s `catalog-info.yaml` file to switch between Argo CD instances as shown in the following example:
+
++
+[source,yaml]
+----
+ annotations:
+ ...
+ # The Argo CD instance name used in `app-config.yaml`.
+
+ argocd/instance-name: '${ARGOCD_INSTANCE}'
+----
+
++
+[NOTE]
+====
+If you do not set this annotation, the Argo CD plugin defaults to the first Argo CD instance configured in `app-config.yaml`.
+====
+
+.Procedure
+
+. Add the following to your dynamic-plugins ConfigMap to enable the Argo CD plugin.
++
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/roadiehq-backstage-plugin-argo-cd-backend-dynamic
+ disabled: false
+ - package: ./dynamic-plugins/dist/backstage-community-plugin-redhat-argocd
+ disabled: false
+----
+
+[role="_additional-resources"]
+.Additional resources
+
+* The package path, scope, and name of the {company-name} ArgoCD plugin has changed since 1.2. For more information, see link:{release-notes-url}#removed-functionality-rhidp-4293[Breaking Changes] in the _{rn-product-title}_.
+
+* For more information on installing dynamic plugins, see link:{installing-and-viewing-dynamic-plugins-url}[{installing-and-viewing-dynamic-plugins-title}].
diff --git a/artifacts/rhdh-plugins-reference/argocd/argocd-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/argocd/argocd-plugin-readme.adoc
new file mode 100644
index 0000000000..b91a49f436
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/argocd/argocd-plugin-readme.adoc
@@ -0,0 +1,36 @@
+= Enabling and configuring Argo CD plugin
+
+You can use the Argo CD plugin to visualize the Continuous Delivery (CD) workflows in OpenShift GitOps. This plugin provides a visual overview of the application’s status, deployment details, commit message, author of the commit, container image promoted to environment and deployment history.
+
+== Using the Argo CD plugin
+
+.Prerequisites
+
+* You have enabled the Argo CD plugin in {product} {product-very-short}.
+
+.Procedures
+
+. Select the *Catalog* tab and choose the component that you want to use.
+
+. Select the *CD* tab to view insights into deployments managed by Argo CD.
+
++
+image::rhdh-plugins-reference/argocd.png[CD tab Argo CD]
+
+. Select an appropriate card to view the deployment details (for example, commit message, author name, and deployment history).
+
++
+image::rhdh-plugins-reference/sidebar.png[Sidebar]
+
+.. Click the link icon (image:rhdh-plugins-reference/link.png[Link icon]) to open the deployment details in Argo CD.
+
+. Select the *Overview* tab and navigate to the Deployment summary section to review the summary of your application's deployment across namespaces. Additionally, select an appropriate Argo CD app to open the deployment details in Argo CD, or select a commit ID from the Revision column to review the changes in GitLab or GitHub.
+
++
+image::rhdh-plugins-reference/deployment_summary.png[Deployment summary]
+
+
+[role="_additional-resources"]
+.Additional resources
+
+* For more information on dynamic plugins, see link:https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.2/html/configuring_plugins_in_red_hat_developer_hub/rhdh-installing-dynamic-plugins[Dynamic plugin installation].
diff --git a/artifacts/rhdh-plugins-reference/argocd/argocd-plugin-user.adoc b/artifacts/rhdh-plugins-reference/argocd/argocd-plugin-user.adoc
new file mode 100644
index 0000000000..2f707b8760
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/argocd/argocd-plugin-user.adoc
@@ -0,0 +1,34 @@
+= Using the Argo CD plugin
+
+You can use the Argo CD plugin to visualize the Continuous Delivery (CD) workflows in OpenShift GitOps. This plugin provides a visual overview of the application’s status, deployment details, commit message, author of the commit, container image promoted to environment and deployment history.
+
+.Prerequisites
+
+* You have enabled the Argo CD plugin in {product} {product-very-short}.
+
+.Procedures
+
+. Select the *Catalog* tab and choose the component that you want to use.
+
+. Select the *CD* tab to view insights into deployments managed by Argo CD.
+
++
+image::rhdh-plugins-reference/argocd.png[CD tab Argo CD]
+
+. Select an appropriate card to view the deployment details (for example, commit message, author name, and deployment history).
+
++
+image::rhdh-plugins-reference/sidebar.png[Sidebar]
+
+.. Click the link icon (image:rhdh-plugins-reference/link.png[Link icon]) to open the deployment details in Argo CD.
+
+. Select the *Overview* tab and navigate to the Deployment summary section to review the summary of your application's deployment across namespaces. Additionally, select an appropriate Argo CD app to open the deployment details in Argo CD, or select a commit ID from the Revision column to review the changes in GitLab or GitHub.
+
++
+image::rhdh-plugins-reference/deployment_summary.png[Deployment summary]
+
+
+[role="_additional-resources"]
+.Additional resources
+
+* For more information on dynamic plugins, see link:https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.2/html/configuring_plugins_in_red_hat_developer_hub/rhdh-installing-dynamic-plugins[Dynamic plugin installation].
diff --git a/artifacts/rhdh-plugins-reference/attributes.adoc b/artifacts/rhdh-plugins-reference/attributes.adoc
new file mode 120000
index 0000000000..cf0dc4a954
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/attributes.adoc
@@ -0,0 +1 @@
+../../artifacts/attributes.adoc
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/images b/artifacts/rhdh-plugins-reference/images
new file mode 120000
index 0000000000..4dc4d26928
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/images
@@ -0,0 +1 @@
+../../images/rhdh-plugins-reference/
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/jfrog-artifactory/jfrog-install-dynamic-plugin.adoc b/artifacts/rhdh-plugins-reference/jfrog-artifactory/jfrog-install-dynamic-plugin.adoc
new file mode 100644
index 0000000000..aba107f535
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/jfrog-artifactory/jfrog-install-dynamic-plugin.adoc
@@ -0,0 +1,15 @@
+.Procedure
+{product-short} dynamically installs the Jfrog Artifactory plugin. To enable it, set the `disabled` property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-jfrog-artifactory
+ disabled: false
+----
+
+.Configuration
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/jfrog-artifactory/jfrog-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/jfrog-artifactory/jfrog-plugin-readme.adoc
new file mode 100644
index 0000000000..fa24848e18
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/jfrog-artifactory/jfrog-plugin-readme.adoc
@@ -0,0 +1,135 @@
+= Jfrog Artifactory
+
+The Jfrog Artifactory plugin displays information about your container images within the Jfrog Artifactory registry.
+
+[IMPORTANT]
+====
+The Jfrog Artifactory plugin is a Technology Preview feature only.
+
+Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+Additional detail on how Red Hat provides support for bundled community dynamic plugins is available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
+
+The Jfrog Artifactory plugin displays information about your container images within the Jfrog Artifactory registry.
+
+== For administrators
+
+=== Installing and configuring the Jfrog Artifactory plugin
+
+ifeval::[{doc-show-dynamic-content} == true]
+include::../../../artifacts/rhdh-plugins-reference/jfrog-artifactory/jfrog-install-dynamic-plugin.adoc[leveloffset=+2]
+endif::[]
+
+ifeval::[{doc-show-dynamic-content} == false]
+The Red Hat Plug-ins for Backstage (RHPIB) packages are hosted in a separate NPM registry, which is maintained by Red Hat. To use these packages, you must adjust your NPM configuration to pull the `@redhat` scoped packages:
+
+[source]
+----
+# update your .npmrc or .yarnrc file
+yarn config set "@redhat:registry" https://npm.registry.redhat.com
+# then pull a package
+yarn add @redhat/backstage-plugin-quay
+----
+
+For more information, see link:https://docs.npmjs.com/cli/v9/configuring-npm/npmrc[npm docs].
+
+Creating a `.npmrc` file ensures that all the packages are scoped under `@redhat` and are fetched from link:https://npm.registry.redhat.com/[Red Hat's NPM registry], while the rest dependencies remain sourced from other link:registry.npmjs.org[registry].
+
+.Procedure
+
+. Run the following command to install the Jfrog Artifactory plugin:
++
+--
+[source,console]
+----
+yarn workspace app add @redhat/backstage-plugin-jfrog-artifactory
+----
+--
+endif::[]
+
+. Set the proxy to the desired Artifactory server in the `app-config.yaml` file as follows:
++
+--
+[source,yaml]
+----
+proxy:
+ '/jfrog-artifactory/api':
+ target: 'http://:8082' # or https://.jfrog.io
+ headers:
+ # Authorization: 'Bearer '
+ # Change to "false" in case of using self hosted artifactory instance with a self-signed certificate
+ secure: true
+----
+--
+
+ifeval::[{doc-show-dynamic-content} == false]
+. Enable the *JFROG ARTIFACTORY* tab on the entity view page in `packages/app/src/components/catalog/EntityPage.tsx` file as follows:
++
+--
+[source]
+----
+/* highlight-add-start */
+import {
+ isJfrogArtifactoryAvailable,
+ JfrogArtifactoryPage,
+} from "@redhat/backstage-plugin-jfrog-artifactory";
+
+/* highlight-add-end */
+
+const serviceEntityPage = (
+
+ // ...
+ {/* highlight-add-start */}
+
+
+
+ {/* highlight-add-end */}
+
+);
+----
+--
+
+. Annotate your entity using the following annotations:
++
+--
+[source,yaml]
+----
+metadata:
+ annotations:
+ 'jfrog-artifactory/image-name': ''
+----
+--
+endif::[]
+
+== For users
+
+=== Using the Jfrog Artifactory plugin in {product-short}
+
+Jfrog Artifactory is a front-end plugin that enables you to view the information about the container images that are available in your Jfrog Artifactory registry.
+
+.Prerequisites
+
+* Your {product-short} application is installed and running.
+* You have installed the Jfrog Artifactory plugin. For installation and configuration steps, see <>.
+
+.Procedure
+
+. Open your {product-short} application and select a component from the *Catalog* page.
+
+. Go to the *JFROG ARTIFACTORY* tab.
++
+--
+image::jfrog-plugin-user1.png[jfrog-tab]
+
+The *JFROG ARTIFACTORY* tab contains a list of container images and related information, such as *VERSION*, *REPOSITORIES*, *MANIFEST*, *MODIFIED*, and *SIZE*.
+--
+
+
+
diff --git a/artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-admin.adoc b/artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-admin.adoc
new file mode 100644
index 0000000000..1c6a5c2632
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-admin.adoc
@@ -0,0 +1,151 @@
+[id="rhdh-keycloak_{context}"]
+= Installing and configuring Keycloak
+
+The Keycloak backend plugin, which integrates Keycloak into {product-short}, has the following capabilities:
+
+* Synchronization of Keycloak users in a realm.
+* Synchronization of Keycloak groups and their users in a realm.
+
+== Installation
+
+The Keycloak plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the `disabled` property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-keycloak-backend-dynamic
+ disabled: false
+----
+
+== Basic configuration
+To enable the Keycloak plugin, you must set the following environment variables:
+
+* `KEYCLOAK_BASE_URL`
+
+* `KEYCLOAK_LOGIN_REALM`
+
+* `KEYCLOAK_REALM`
+
+* `KEYCLOAK_CLIENT_ID`
+
+* `KEYCLOAK_CLIENT_SECRET`
+
+== Advanced configuration
+
+.Schedule configuration
+You can configure a schedule in the `app-config.yaml` file, as follows:
+
+[source,yaml]
+----
+ catalog:
+ providers:
+ keycloakOrg:
+ default:
+ # ...
+ # highlight-add-start
+ schedule: # optional; same options as in TaskScheduleDefinition
+ # supports cron, ISO duration, "human duration" as used in code
+ frequency: { minutes: 1 }
+ # supports ISO duration, "human duration" as used in code
+ timeout: { minutes: 1 }
+ initialDelay: { seconds: 15 }
+ # highlight-add-end
+----
+
+[NOTE]
+====
+If you have made any changes to the schedule in the `app-config.yaml` file, then restart to apply the changes.
+====
+
+.Keycloak query parameters
+
+You can override the default Keycloak query parameters in the `app-config.yaml` file, as follows:
+
+[source,yaml]
+----
+ catalog:
+ providers:
+ keycloakOrg:
+ default:
+ # ...
+ # highlight-add-start
+ userQuerySize: 500 # Optional
+ groupQuerySize: 250 # Optional
+ # highlight-add-end
+----
+
+Communication between {product-short} and Keycloak is enabled by using the Keycloak API. Username and password, or client credentials are supported authentication methods.
+
+
+The following table describes the parameters that you can configure to enable the plugin under `catalog.providers.keycloakOrg.` object in the `app-config.yaml` file:
+
+|===
+| Name | Description | Default Value | Required
+
+| `baseUrl`
+| Location of the Keycloak server, such as `pass:c[https://localhost:8443/auth]`. Note that the newer versions of Keycloak omit the `/auth` context path.
+| ""
+| Yes
+
+| `realm`
+| Realm to synchronize
+| `master`
+| No
+
+| `loginRealm`
+| Realm used to authenticate
+| `master`
+| No
+
+| `username`
+| Username to authenticate
+| ""
+| Yes if using password based authentication
+
+| `password`
+| Password to authenticate
+| ""
+| Yes if using password based authentication
+
+| `clientId`
+| Client ID to authenticate
+| ""
+| Yes if using client credentials based authentication
+
+| `clientSecret`
+| Client Secret to authenticate
+| ""
+| Yes if using client credentials based authentication
+
+| `userQuerySize`
+| Number of users to query at a time
+| `100`
+| No
+
+| `groupQuerySize`
+| Number of groups to query at a time
+| `100`
+| No
+|===
+
+When using client credentials, the access type must be set to `confidential` and service accounts must be enabled. You must also add the following roles from the `realm-management` client role:
+
+* `query-groups`
+* `query-users`
+* `view-users`
+
+== Limitations
+
+If you have self-signed or corporate certificate issues, you can set the following environment variable before starting {product-short}:
+
+`NODE_TLS_REJECT_UNAUTHORIZED=0`
+
+
+[NOTE]
+====
+The solution of setting the environment variable is not recommended.
+====
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-readme.adoc
new file mode 100644
index 0000000000..005e544e72
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-readme.adoc
@@ -0,0 +1,180 @@
+[id="rhdh-keycloak_{context}"]
+= Installation and configuration of Keycloak
+
+The Keycloak backend plugin, which integrates Keycloak into {product-short}, has the following capabilities:
+
+* Synchronization of Keycloak users in a realm.
+* Synchronization of Keycloak groups and their users in a realm.
+
+== For administrators
+
+=== Installation
+
+The Keycloak plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the `disabled` property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-keycloak-backend-dynamic
+ disabled: false
+----
+
+=== Basic configuration
+To enable the Keycloak plugin, you must set the following environment variables:
+
+* `KEYCLOAK_BASE_URL`
+
+* `KEYCLOAK_LOGIN_REALM`
+
+* `KEYCLOAK_REALM`
+
+* `KEYCLOAK_CLIENT_ID`
+
+* `KEYCLOAK_CLIENT_SECRET`
+
+=== Advanced configuration
+
+.Schedule configuration
+You can configure a schedule in the `app-config.yaml` file, as follows:
+
+[source,yaml]
+----
+ catalog:
+ providers:
+ keycloakOrg:
+ default:
+ # ...
+ # highlight-add-start
+ schedule: # optional; same options as in TaskScheduleDefinition
+ # supports cron, ISO duration, "human duration" as used in code
+ frequency: { minutes: 1 }
+ # supports ISO duration, "human duration" as used in code
+ timeout: { minutes: 1 }
+ initialDelay: { seconds: 15 }
+ # highlight-add-end
+----
+
+[NOTE]
+====
+If you have made any changes to the schedule in the `app-config.yaml` file, then restart to apply the changes.
+====
+
+.Keycloak query parameters
+
+You can override the default Keycloak query parameters in the `app-config.yaml` file, as follows:
+
+[source,yaml]
+----
+ catalog:
+ providers:
+ keycloakOrg:
+ default:
+ # ...
+ # highlight-add-start
+ userQuerySize: 500 # Optional
+ groupQuerySize: 250 # Optional
+ # highlight-add-end
+----
+
+Communication between {product-short} and Keycloak is enabled by using the Keycloak API. Username and password, or client credentials are supported authentication methods.
+
+
+The following table describes the parameters that you can configure to enable the plugin under `catalog.providers.keycloakOrg.` object in the `app-config.yaml` file:
+
+|===
+| Name | Description | Default Value | Required
+
+| `baseUrl`
+| Location of the Keycloak server, such as `pass:c[https://localhost:8443/auth]`. Note that the newer versions of Keycloak omit the `/auth` context path.
+| ""
+| Yes
+
+| `realm`
+| Realm to synchronize
+| `master`
+| No
+
+| `loginRealm`
+| Realm used to authenticate
+| `master`
+| No
+
+| `username`
+| Username to authenticate
+| ""
+| Yes if using password based authentication
+
+| `password`
+| Password to authenticate
+| ""
+| Yes if using password based authentication
+
+| `clientId`
+| Client ID to authenticate
+| ""
+| Yes if using client credentials based authentication
+
+| `clientSecret`
+| Client Secret to authenticate
+| ""
+| Yes if using client credentials based authentication
+
+| `userQuerySize`
+| Number of users to query at a time
+| `100`
+| No
+
+| `groupQuerySize`
+| Number of groups to query at a time
+| `100`
+| No
+|===
+
+When using client credentials, the access type must be set to `confidential` and service accounts must be enabled. You must also add the following roles from the `realm-management` client role:
+
+* `query-groups`
+* `query-users`
+* `view-users`
+
+=== Limitations
+
+If you have self-signed or corporate certificate issues, you can set the following environment variable before starting {product-short}:
+
+`NODE_TLS_REJECT_UNAUTHORIZED=0`
+
+
+[NOTE]
+====
+The solution of setting the environment variable is not recommended.
+====
+
+== For users
+
+=== Import of users and groups in {product-short} using the Keycloak plugin
+
+After configuring the plugin successfully, the plugin imports the users and groups each time when started.
+
+[NOTE]
+====
+If you set up a schedule, users and groups will also be imported.
+====
+
+After the first import is complete, you can select *User* to list the users from the catalog page:
+
+image::rhdh-plugins-reference/users.jpg[catalog-list]
+
+You can see the list of users on the page:
+
+image::rhdh-plugins-reference/user-list.jpg[user-list]
+
+When you select a user, you can see the information imported from Keycloak:
+
+image::rhdh-plugins-reference/user2.jpg[user-profile]
+
+You can also select a group, view the list, and select or view the information imported from Keycloak for a group:
+
+image::rhdh-plugins-reference/group1.jpg[group-profile]
diff --git a/artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-user.adoc b/artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-user.adoc
new file mode 100644
index 0000000000..cf91a17ba0
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-user.adoc
@@ -0,0 +1,32 @@
+[id="rhdh-keycloak_{context}"]
+= Using Keycloak
+
+The Keycloak backend plugin, which integrates Keycloak into {product-short}, has the following capabilities:
+
+* Synchronization of Keycloak users in a realm.
+* Synchronization of Keycloak groups and their users in a realm.
+
+== Importing users and groups in {product-short} using the Keycloak plugin
+
+After configuring the plugin successfully, the plugin imports the users and groups each time when started.
+
+[NOTE]
+====
+If you set up a schedule, users and groups will also be imported.
+====
+
+After the first import is complete, you can select *User* to list the users from the catalog page:
+
+image::rhdh-plugins-reference/users.jpg[catalog-list]
+
+You can see the list of users on the page:
+
+image::rhdh-plugins-reference/user-list.jpg[user-list]
+
+When you select a user, you can see the information imported from Keycloak:
+
+image::rhdh-plugins-reference/user2.jpg[user-profile]
+
+You can also select a group, view the list, and select or view the information imported from Keycloak for a group:
+
+image::rhdh-plugins-reference/group1.jpg[group-profile]
diff --git a/artifacts/rhdh-plugins-reference/modules b/artifacts/rhdh-plugins-reference/modules
new file mode 120000
index 0000000000..8b0e854007
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/modules
@@ -0,0 +1 @@
+../../modules
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-install-dynamic-plugin.adoc b/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-install-dynamic-plugin.adoc
new file mode 100644
index 0000000000..97af95a3d5
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-install-dynamic-plugin.adoc
@@ -0,0 +1,14 @@
+The Nexus Repository Manager plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the disabled property to false as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-nexus-repository-manager
+ disabled: false
+----
+
+.Configuration
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-admin.adoc b/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-admin.adoc
new file mode 100644
index 0000000000..605e414994
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-admin.adoc
@@ -0,0 +1,77 @@
+[id="installing-configuring-nexus-plugin"]
+= Installing and configuring the Nexus Repository Manager plugin
+
+The Nexus Repository Manager plugin displays the information about your build artifacts in your {product-short} application. The build artifacts are available in the Nexus Repository Manager.
+
+[IMPORTANT]
+====
+The Nexus Repository Manager plugin is a Technology Preview feature only.
+
+Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+Additional detail on how Red Hat provides support for bundled community dynamic plugins is available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
+
+== Installation
+The Nexus Repository Manager plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the disabled property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-nexus-repository-manager
+ disabled: false
+----
+
+== Configuration
+. Set the proxy to the desired Nexus Repository Manager server in the `app-config.yaml` file as follows:
++
+[source,yaml]
+----
+proxy:
+ '/nexus-repository-manager':
+ target: 'https://'
+ headers:
+ X-Requested-With: 'XMLHttpRequest'
+ # Uncomment the following line to access a private Nexus Repository Manager using a token
+ # Authorization: 'Bearer '
+ changeOrigin: true
+ # Change to "false" in case of using self hosted Nexus Repository Manager instance with a self-signed certificate
+ secure: true
+----
+
+. Optional: Change the base URL of Nexus Repository Manager proxy as follows:
++
+[source,yaml]
+----
+nexusRepositoryManager:
+ # default path is `/nexus-repository-manager`
+ proxyPath: /custom-path
+----
+
+. Optional: Enable the following experimental annotations:
++
+[source,yaml]
+----
+nexusRepositoryManager:
+ experimentalAnnotations: true
+----
+
+. Annotate your entity using the following annotations:
++
+[source,yaml]
+----
+metadata:
+ annotations:
+ # insert the chosen annotations here
+ # example
+ nexus-repository-manager/docker.image-name: `/`,
+----
+
+//Cannot xref across titles. Convert xref to a link.
+//For additional information about installing and configuring dynamic plugins, see the xref:rhdh-installing-dynamic-plugins[] section.
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-readme.adoc
new file mode 100644
index 0000000000..46f67acf1b
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-readme.adoc
@@ -0,0 +1,102 @@
+= Installation and configuration of Nexus Repository Manager
+
+The Nexus Repository Manager plugin displays the information about your build artifacts in your {product-short} application. The build artifacts are available in the Nexus Repository Manager.
+
+[IMPORTANT]
+====
+The Nexus Repository Manager plugin is a Technology Preview feature only.
+
+Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+Additional detail on how Red Hat provides support for bundled community dynamic plugins is available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
+
+== For administrators
+
+=== Installing and configuring the Nexus Repository Manager plugin
+
+.Installation
+The Nexus Repository Manager plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the disabled property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-nexus-repository-manager
+ disabled: false
+----
+
+.Configuration
+. Set the proxy to the desired Nexus Repository Manager server in the `app-config.yaml` file as follows:
++
+[source,yaml]
+----
+proxy:
+ '/nexus-repository-manager':
+ target: 'https://'
+ headers:
+ X-Requested-With: 'XMLHttpRequest'
+ # Uncomment the following line to access a private Nexus Repository Manager using a token
+ # Authorization: 'Bearer '
+ changeOrigin: true
+ # Change to "false" in case of using self hosted Nexus Repository Manager instance with a self-signed certificate
+ secure: true
+----
+
+. Optional: Change the base URL of Nexus Repository Manager proxy as follows:
++
+[source,yaml]
+----
+nexusRepositoryManager:
+ # default path is `/nexus-repository-manager`
+ proxyPath: /custom-path
+----
+
+. Optional: Enable the following experimental annotations:
++
+[source,yaml]
+----
+nexusRepositoryManager:
+ experimentalAnnotations: true
+----
+
+. Annotate your entity using the following annotations:
++
+[source,yaml]
+----
+metadata:
+ annotations:
+ # insert the chosen annotations here
+ # example
+ nexus-repository-manager/docker.image-name: `/`,
+----
+
+//Cannot xref across titles. Convert xref to a link.
+//For additional information about installing and configuring dynamic plugins, see the xref:rhdh-installing-dynamic-plugins[] section.
+
+== For users
+
+=== Using the Nexus Repository Manager plugin in {product-short}
+
+The Nexus Repository Manager is a front-end plugin that enables you to view the information about build artifacts.
+
+.Prerequisites
+
+- Your {product-short} application is installed and running.
+- You have installed the Nexus Repository Manager plugin. For the installation process, see <>.
+
+.Procedure
+
+1. Open your {product-short} application and select a component from the *Catalog* page.
+2. Go to the *BUILD ARTIFACTS* tab.
++
+--
+The *BUILD ARTIFACTS* tab contains a list of build artifacts and related information, such as *VERSION*, *REPOSITORY*, *REPOSITORY TYPE*, *MANIFEST*, *MODIFIED*, and *SIZE*.
+
+image::rhdh-plugins-reference/nexus-repository-manager.png[nexus-repository-manager-tab]
+--
diff --git a/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-user.adoc b/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-user.adoc
new file mode 100644
index 0000000000..6c27f14dc4
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-user.adoc
@@ -0,0 +1,33 @@
+= Using the Nexus Repository Manager plugin
+
+The Nexus Repository Manager plugin displays the information about your build artifacts in your {product-short} application. The build artifacts are available in the Nexus Repository Manager.
+
+[IMPORTANT]
+====
+The Nexus Repository Manager plugin is a Technology Preview feature only.
+
+Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+Additional detail on how Red Hat provides support for bundled community dynamic plugins is available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
+
+The Nexus Repository Manager is a front-end plugin that enables you to view the information about build artifacts.
+
+.Prerequisites
+
+- Your {product-short} application is installed and running.
+- You have installed the Nexus Repository Manager plugin.
+//For the installation process, see xref:installing-configuring-nexus-plugin[Installing and configuring the Nexus Repository Manager plugin].
+
+.Procedure
+
+1. Open your {product-short} application and select a component from the *Catalog* page.
+2. Go to the *BUILD ARTIFACTS* tab.
++
+--
+The *BUILD ARTIFACTS* tab contains a list of build artifacts and related information, such as *VERSION*, *REPOSITORY*, *REPOSITORY TYPE*, *MANIFEST*, *MODIFIED*, and *SIZE*.
+
+image::rhdh-plugins-reference/nexus-repository-manager.png[nexus-repository-manager-tab]
+--
diff --git a/artifacts/rhdh-plugins-reference/ocm/ocm-backend-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/ocm/ocm-backend-plugin-readme.adoc
new file mode 100644
index 0000000000..74a63c1ade
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/ocm/ocm-backend-plugin-readme.adoc
@@ -0,0 +1,5 @@
+= Open Cluster Management plugin for Backstage
+
+The Open Cluster Management (OCM) plugin integrates your Backstage instance with OCM.
+
+For more information about OCM plugin, see the https://github.com/janus-idp/backstage-plugins/tree/main/plugins/ocm[Open Cluster Management plugin documentation] on GitHub.
diff --git a/artifacts/rhdh-plugins-reference/ocm/ocm-common-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/ocm/ocm-common-plugin-readme.adoc
new file mode 100644
index 0000000000..74a63c1ade
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/ocm/ocm-common-plugin-readme.adoc
@@ -0,0 +1,5 @@
+= Open Cluster Management plugin for Backstage
+
+The Open Cluster Management (OCM) plugin integrates your Backstage instance with OCM.
+
+For more information about OCM plugin, see the https://github.com/janus-idp/backstage-plugins/tree/main/plugins/ocm[Open Cluster Management plugin documentation] on GitHub.
diff --git a/artifacts/rhdh-plugins-reference/ocm/ocm-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/ocm/ocm-plugin-readme.adoc
new file mode 100644
index 0000000000..504259a992
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/ocm/ocm-plugin-readme.adoc
@@ -0,0 +1,439 @@
+= Open Cluster Management plugin for Backstage
+
+The Open Cluster Management (OCM) plugin integrates your Backstage instance with the `MultiClusterHub` and `MultiCluster` engines of OCM.
+
+== Capabilities
+
+The OCM plugin has the following capabilities:
+
+* All clusters represented as `ManagedCluster` in `MultiClusterHub` or MCE are discovered and imported into the Backstage catalog, such as:
+ ** Entity is defined as `kind: Resource` with `spec.type` set to `kubernetes-cluster`.
+ ** Links to the OpenShift Container Platform (OCP) console, OCM console, and OpenShift Cluster Manager are provided in `metadata.links`.
+* Shows real-time data from OCM on the Resource entity page, including:
+ ** Cluster current status (up or down)
+ ** Cluster nodes status (up or down)
+ ** Cluster details (console link, OCP, and Kubernetes version)
+ ** Details about available compute resources on the cluster
+
+== For administrators
+
+=== Installation
+
+The Red Hat Plug-ins for Backstage (RHPIB) packages are hosted in a separate NPM registry, which is maintained by Red Hat. To use these packages, you must adjust your NPM configuration to pull the `@redhat` scoped packages:
+
+[source]
+----
+# update your .npmrc or .yarnrc file
+yarn config set "@redhat:registry" https://npm.registry.redhat.com
+# then pull a package
+yarn add @redhat/backstage-plugin-quay
+----
+
+For more information, see link:https://docs.npmjs.com/cli/v9/configuring-npm/npmrc[npm docs].
+
+Creating a `.npmrc` file ensures that all the packages are scoped under `@redhat` and are fetched from link:https://npm.registry.redhat.com/[Red Hat's NPM registry], while the rest dependencies remain sourced from other link:registry.npmjs.org[registry].
+
+Using this configuration, you can proceed with the installation of the individual packages.
+
+The OCM plugin is composed of two packages, including:
+
+* `@redhat/backstage-plugin-ocm-backend` package connects the Backstage server to OCM. For setup process, see <> section.
+* The `@redhat/backstage-plugin-ocm` package, which contains frontend components requires the `\*-backend` package to be present and properly set up. For detailed instructions on setting up the backend, refer to the <> section.
+
+[NOTE]
+====
+If you are interested in Resource discovery and do not want any of the front-end components, then you can install and configure the `@redhat/backstage-plugin-ocm-backend` package only.
+====
+
+
+==== Prerequisites
+
+* OCM is deployed and configured on a Kubernetes cluster.
+* https://backstage.io/docs/features/kubernetes[Kubernetes plugin for Backstage] is installed.
+* A `ClusterRole` is granted to `ServiceAccount` accessing the hub cluster as follows:
++
+--
+[source,yaml]
+----
+ kind: ClusterRole
+ apiVersion: rbac.authorization.k8s.io/v1
+ metadata:
+ name: backstage-ocm-plugin
+ rules:
+ - apiGroups:
+ - cluster.open-cluster-management.io
+ resources:
+ - managedclusters
+ verbs:
+ - get
+ - watch
+ - list
+ - apiGroups:
+ - internal.open-cluster-management.io
+ resources:
+ - managedclusterinfos
+ verbs:
+ - get
+ - watch
+ - list
+----
+--
+
+==== Setting up the OCM backend package
+
+. Install the OCM backend plugin using the following command:
++
+--
+[source,console]
+----
+yarn workspace backend add @redhat/backstage-plugin-ocm-backend
+----
+--
+
+. Configure the OCM backend plugin using one of the following configurations:
+** The OCM configuration provides the information about your hub. To use the OCM configuration, add the following code to your `app-config.yaml` file:
++
+--
+[source,yaml]
+----
+`yaml title="app-config.yaml"
+ catalog:
+ providers:
+ ocm:
+ env: # Key is reflected as provider ID. Defines and claims plugin instance ownership of entities
+ name: # Name that the hub cluster will assume in Backstage Catalog (in OCM this is always local-cluster which can be confusing)
+ url: # Url of the hub cluster API endpoint
+ serviceAccountToken: # Token used for querying data from the hub
+ skipTLSVerify: # Skip TLS certificate verification, defaults to false
+ caData: # Base64-encoded CA bundle in PEM format
+
+----
+--
+
+** If the Backstage Kubernetes plugin is installed and configured to connect to the hub cluster, then you can bind the both hub and Kubernetes configuration by providing the name of the hub in the `app-config.yaml` as follows:
++
+--
+[source,yaml]
+----
+```yaml title="app-config.yaml"
+ kubernetes:
+ serviceLocatorMethod:
+ type: 'multiTenant'
+ clusterLocatorMethods:
+ - type: 'config'
+ clusters:
+ # highlight-next-line
+ - name:
+ # ...
+
+ catalog:
+ providers:
+ ocm:
+ env: # Key is reflected as provider ID. Defines and claims plugin instance ownership of entities
+ # highlight-next-line
+ kubernetesPluginRef: # Match the cluster name in kubernetes plugin config
+----
+
+Ensure that the Backstage uses a `ServiceAccount` token and the required permissions are granted as mentioned previously.
+
+This is useful when you already use a Kubernetes plugin in your Backstage instance. Also, the hub cluster must be connected using the `ServiceAccount`.
+
+For more information about the configuration, see https://backstage.io/docs/features/kubernetes/configuration#configuring-kubernetes-clusters[Backstage Kubernetes plugin] documentation.
+--
+
+. Create a new plugin instance in `packages/backend/src/plugins/ocm.ts` file as follows:
++
+--
+[source]
+----
+```ts title="packages/backend/src/plugins/ocm.ts"
+ import { Router } from 'express';
+
+ import { createRouter } from '@redhat/backstage-plugin-ocm-backend';
+
+ import { PluginEnvironment } from '../types';
+
+ export default async function createPlugin(
+ env: PluginEnvironment,
+ ): Promise {
+ return await createRouter({
+ logger: env.logger,
+ config: env.config,
+ });
+ }
+----
+--
+
+. Import and plug the new instance into `packages/backend/src/index.ts` file:
++
+--
+[source]
+----
+```ts title="packages/backend/src/index.ts"
+ /* highlight-add-next-line */
+ import ocm from './plugins/ocm';
+
+ async function main() {
+ // ...
+ const createEnv = makeCreateEnv(config);
+ // ...
+ /* highlight-add-next-line */
+ const ocmEnv = useHotMemoize(module, () => createEnv('ocm'));
+ // ...
+ const apiRouter = Router();
+ // ...
+ /* highlight-add-next-line */
+ apiRouter.use('/ocm', await ocm(ocmEnv));
+ // ...
+ }
+```
+----
+--
+
+. Import the cluster `Resource` entity provider into the `catalog` plugin in the `packages/backend/src/plugins/catalog.ts` file. The scheduler also needs to be configured. Two configurations are possible here:
+ .. Configure the scheduler inside the `app-config.yaml`:
++
+--
+[source,yaml]
+----
+```yaml title="app-config.yaml"
+ catalog:
+ providers:
+ ocm:
+ env:
+ # ...
+ # highlight-add-start
+ schedule: # optional; same options as in TaskScheduleDefinition
+ # supports cron, ISO duration, "human duration" as used in code
+ frequency: { minutes: 1 }
+ # supports ISO duration, "human duration" as used in code
+ timeout: { minutes: 1 }
+ # highlight-add-end
++
+----
+
+and then use the configured scheduler
+
+[source]
+----
+```ts title="packages/backend/src/index.ts"
+ /* highlight-add-next-line */
+ import { ManagedClusterProvider } from '@redhat/backstage-plugin-ocm-backend';
+
+ export default async function createPlugin(
+ env: PluginEnvironment,
+ ): Promise {
+ const builder = await CatalogBuilder.create(env);
+ // ...
+ /* highlight-add-start */
+ const ocm = ManagedClusterProvider.fromConfig(env.config, {
+ logger: env.logger,
+ scheduler: env.scheduler,
+ });
+ builder.addEntityProvider(ocm);
+ /* highlight-add-start */
+ // ...
+ }
+----
+--
+
+.. Add a schedule directly inside the `packages/backend/src/plugins/catalog.ts` file
++
+--
+[source]
+----
+```ts title="packages/backend/src/index.ts"
+ /* highlight-add-next-line */
+ import { ManagedClusterProvider } from '@redhat/backstage-plugin-ocm-backend';
+
+ export default async function createPlugin(
+ env: PluginEnvironment,
+ ): Promise {
+ const builder = await CatalogBuilder.create(env);
+ // ...
+ /* highlight-add-start */
+ const ocm = ManagedClusterProvider.fromConfig(env.config, {
+ logger: env.logger,
+ schedule: env.scheduler.createScheduledTaskRunner({
+ frequency: { minutes: 1 },
+ timeout: { minutes: 1 },
+ }),
+ });
+ builder.addEntityProvider(ocm);
+ /* highlight-add-start */
+ // ...
+ }
+----
+--
+
+. Optional: Configure the default owner for the cluster entities in the catalog for a specific environment. For example, use the following code to set `foo` as the owner for clusters from `env` in the `app-config.yaml` catalog section:
++
+--
+[source,yaml]
+----
+`yaml title="app-config.yaml"
+ catalog:
+ providers:
+ ocm:
+ env:
+ # highlight-next-line
+ owner: user:foo
+----
+
+For more information about the default owner configuration, see https://backstage.io/docs/features/software-catalog/references/#string-references[upstream string references documentation].
+--
+
+==== Setting up the OCM frontend package
+
+. Install the OCM frontend plugin using the following command:
++
+--
+[source,console]
+----
+yarn workspace app add @redhat/backstage-plugin-ocm
+----
+--
+
+. Select the components that you want to use, such as:
+
+** `OcmPage`: This is a standalone page or dashboard displaying all clusters as tiles. You can add `OcmPage` to `packages/app/src/App.tsx` file as follows:
++
+--
+[source]
+----
+```tsx title="packages/app/src/App.tsx"
+ /* highlight-add-next-line */
+ import { OcmPage } from '@redhat/backstage-plugin-ocm';
+
+ const routes = (
+
+ {/* ... */}
+ {/* highlight-add-next-line */}
+ } />} />
+
+ );
+----
+
+You can also update navigation in `packages/app/src/components/Root/Root.tsx` as follows:
+
+[source]
+----
+```tsx title="packages/app/src/components/Root/Root.tsx"
+ /* highlight-add-next-line */
+ import StorageIcon from '@material-ui/icons/Storage';
+
+ export const Root = ({ children }: PropsWithChildren<{}>) => (
+
+
+ }>
+ {/* ... */}
+ {/* highlight-add-next-line */}
+
+
+ {/* ... */}
+
+ {children}
+
+ );
+----
+--
+
+** `ClusterContextProvider`: This component is a React context provided for OCM data, which is related to the current entity. The `ClusterContextProvider` component is used to display any data on the React components mentioned in `packages/app/src/components/catalog/EntityPage.tsx`:
++
+--
+[source]
+----
+```tsx title="packages/app/src/components/catalog/EntityPage.tsx"
+ /* highlight-add-start */
+ import {
+ ClusterAvailableResourceCard,
+ ClusterContextProvider,
+ ClusterInfoCard,
+ } from '@redhat/backstage-plugin-ocm';
+
+ /* highlight-add-end */
+
+ const isType = (types: string | string[]) => (entity: Entity) => {
+ if (!entity?.spec?.type) {
+ return false;
+ }
+ return typeof types === 'string'
+ ? entity?.spec?.type === types
+ : types.includes(entity.spec.type as string);
+ };
+
+ export const resourcePage = (
+
+ {/* ... */}
+ {/* highlight-add-start */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* highlight-add-end */}
+
+ );
+
+ export const entityPage = (
+
+ {/* ... */}
+ {/* highlight-add-next-line */}
+
+
+ );
+----
+
+In the previous codeblock, you can place the context provider into your `Resource` entity renderer, which is usually available in `packages/app/src/components/catalog/EntityPage.tsx` or in an imported component.
+
+ ** ``: This is an entity component displaying details of a cluster in a table:
+ ** ``: This is an entity component displaying the available resources on a cluster. For example, see https://open-cluster-management.io/concepts/managedcluster/#cluster-heartbeats-and-status[`.status.capacity`] of the `ManagedCluster` resource.
+--
+
+== For users
+
+=== Using the OCM plugin in Backstage
+
+The OCM plugin integrates your Backstage instance with multi-cluster engines and displays real-time data from OCM.
+
+==== Prerequisites
+
+* Your Backstage application is installed and running.
+* You have installed the OCM plugin. For the installation process, see <>.
+
+==== Procedure
+
+. Open your Backstage application.
+. Click the *Clusters* tab from the left-side panel to view the *Managed Clusters* page.
++
+--
+The *Managed Clusters* page displays the list of clusters with additional information, such as status, infrastructure provider, associated OpenShift version, and available nodes.
+
+image::ocm-plugin-user1.png[ocm-plugin-ui]
+
+You can also upgrade the OpenShift version for a cluster using the *Upgrade available* option in the *VERSION* column.
+--
+
+. Select a cluster from the *Managed Clusters* to view the related cluster information.
++
+--
+You are redirected to the cluster-specific page, which consists of:
+
+ ** *Cluster Information*, such as name, status, accessed Kubernetes version, associated OpenShift ID and version, and accessed platform.
+ ** *Available* cluster capacity, including CPU cores, memory size, and number of pods.
+ ** *Related Links*, which enable you to access different consoles directly, such as OpenShift Console, OCM Console, and OpenShift Cluster Manager Console.
+ ** *Relations* card, which displays the visual representation of the cluster and associated dependencies.
+
+image::ocm-plugin-user2.png[ocm-plugin-ui]
+--
diff --git a/artifacts/rhdh-plugins-reference/quay/quay-install-dynamic-plugin.adoc b/artifacts/rhdh-plugins-reference/quay/quay-install-dynamic-plugin.adoc
new file mode 100644
index 0000000000..7c26e4a40f
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/quay/quay-install-dynamic-plugin.adoc
@@ -0,0 +1,15 @@
+.Installation
+The Quay plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the `disabled` property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-quay
+ disabled: false
+----
+
+.Configuration
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/quay/quay-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/quay/quay-plugin-readme.adoc
new file mode 100644
index 0000000000..c0dd3f9b2a
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/quay/quay-plugin-readme.adoc
@@ -0,0 +1,127 @@
+= Quay
+
+The Quay plugin displays the information about your container images within the Quay registry in your {product-short} application.
+
+== For administrators
+
+[[installation]]
+=== Installing and configuring the Quay plugin
+
+ifeval::[{doc-show-dynamic-content} == true]
+include::../../../artifacts/rhdh-plugins-reference/acr/acr-install-dynamic-plugin.adoc[leveloffset=+2]
+endif::[]
+
+ifeval::[{doc-show-dynamic-content} == false]
+The Red Hat Plug-ins for Backstage (RHPIB) packages are hosted in a separate NPM registry, which is maintained by Red Hat. To use these packages, you must adjust your NPM configuration to pull the `@redhat` scoped packages:
+
+[source]
+----
+# update your .npmrc or .yarnrc file
+yarn config set "@redhat:registry" https://npm.registry.redhat.com
+# then pull a package
+yarn add @redhat/backstage-plugin-quay
+----
+
+For more information, see link:https://docs.npmjs.com/cli/v9/configuring-npm/npmrc[npm docs].
+
+Creating a `.npmrc` file ensures that all the packages are scoped under `@redhat` and are fetched from link:https://npm.registry.redhat.com/[Red Hat's NPM registry], while the rest dependencies remain sourced from other link:registry.npmjs.org[registry].
+
+You can now install the Quay plugin using the following command:
+
+[source,console]
+----
+yarn workspace app add @redhat/backstage-plugin-quay
+----
+endif::[]
+
+
+. Set the proxy to the desired Quay server in the `app-config.yaml` file as follows:
++
+--
+[source,yaml]
+----
+ ```yaml title="app-config.yaml"
+ proxy:
+ '/quay/api':
+ target: 'https://quay.io'
+ headers:
+ X-Requested-With: 'XMLHttpRequest'
+ # Uncomment the following line to access a private Quay Repository using a token
+ # Authorization: 'Bearer '
+ changeOrigin: true
+ # Change to "false" in case of using self hosted quay instance with a self-signed certificate
+ secure: true
+
+ quay:
+ # The UI url for Quay, used to generate the link to Quay
+ uiUrl: 'https://quay.io'
+ ```
+----
+--
+
+ifeval::[{doc-show-dynamic-content} == false]
+. Enable an additional tab on the entity view page in `packages/app/src/components/catalog/EntityPage.tsx`:
++
+--
+[source]
+----
+ ```tsx title="packages/app/src/components/catalog/EntityPage.tsx"
+ /* highlight-add-next-line */
+ import { isQuayAvailable, QuayPage } from '@redhat/backstage-plugin-quay';
+
+ const serviceEntityPage = (
+
+ {/* ... */}
+ {/* highlight-add-next-line */}
+
+
+
+
+ );
+ ```
+----
+--
+endif::[]
+
+. Annotate your entity with the following annotations:
++
+--
+[source,yaml]
+----
+ ```yaml title="catalog-info.yaml"
+ metadata:
+ annotations:
+ 'quay.io/repository-slug': `/',
+ ```
+----
+--
+
+== For users
+
+=== Using the Quay plugin in {product-short}
+
+Quay is a front-end plugin that enables you to view the information about the container images.
+
+.Prerequisites
+
+* Your {product-short} application is installed and running.
+* You have installed the Quay plugin. For installation process, see <>.
+
+.Procedure
+
+. Open your {product-short} application and select a component from the *Catalog* page.
+. Go to the *Image Registry* tab.
++
+The *Image Registry* tab in the {product-short} UI contains a list of container images and related information, such as *TAG*, *LAST MODIFIED*, *SECURITY SCAN*, *SIZE*, *EXPIRES*, and *MANIFEST*.
++
+image::quay-plugin-backstage1.png[quay-tab]
+
+. If a container image does not pass the security scan, select the security scan value of the image to check the vulnerabilities.
++
+image::quay-plugin-backstage2.png[quay-tab]
++
+The vulnerabilities page displays the associated advisory with a link, severity, package name, and current and fixed versions.
++
+image::quay-plugin-backstage3.png[quay-tab-vulnerabilities]
++
+The advisory link redirects to the Red Hat Security Advisory page that contains detailed information about the advisory, including the solution.
diff --git a/artifacts/rhdh-plugins-reference/snip-concious-language.adoc b/artifacts/rhdh-plugins-reference/snip-concious-language.adoc
new file mode 120000
index 0000000000..1bd106d7d0
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/snip-concious-language.adoc
@@ -0,0 +1 @@
+../../artifacts/snip-conscious-language.adoc
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/tekton/tekton-install-dynamic-plugin.adoc b/artifacts/rhdh-plugins-reference/tekton/tekton-install-dynamic-plugin.adoc
new file mode 100644
index 0000000000..4b876988ee
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/tekton/tekton-install-dynamic-plugin.adoc
@@ -0,0 +1,13 @@
+.Installation
+{product-short} dynamically installs the Tekton plugin. To enable it, set the `disabled` property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-tekton
+ disabled: false
+----
diff --git a/artifacts/rhdh-plugins-reference/tekton/tekton-plugin-admin.adoc b/artifacts/rhdh-plugins-reference/tekton/tekton-plugin-admin.adoc
new file mode 100644
index 0000000000..2e5d8bba25
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/tekton/tekton-plugin-admin.adoc
@@ -0,0 +1,143 @@
+[[installation-and-configuration-tekton]]
+= Installing and configuring the Tekton plugin
+
+You can use the Tekton plugin to visualize the results of CI/CD pipeline runs on your Kubernetes or OpenShift clusters. The plugin allows users to visually see high level status of all associated tasks in the pipeline for their applications.
+
+[[installing-tekton-plugin]]
+== Installation
+
+.Prerequsites
+* You have installed and configured the `@backstage/plugin-kubernetes` and `@backstage/plugin-kubernetes-backend` dynamic plugins.
+//For more information about installing dynamic plugins, see xref:rhdh-installing-dynamic-plugins[].
+//Cannot xref across titles. Convert xref to a link.
+
+* You have configured the Kubernetes plugin to connect to the cluster using a `ServiceAccount`.
+
+* The `ClusterRole` must be granted for custom resources (PipelineRuns and TaskRuns) to the `ServiceAccount` accessing the cluster.
++
+[NOTE]
+If you have the RHDH Kubernetes plugin configured, then the `ClusterRole` is already granted.
+
+* To view the pod logs, you have granted permissions for `pods/log`.
+
+* You can use the following code to grant the `ClusterRole` for custom resources and pod logs:
++
+--
+[source,yaml]
+----
+kubernetes:
+ ...
+ customResources:
+ - group: 'tekton.dev'
+ apiVersion: 'v1'
+ plural: 'pipelineruns'
+ - group: 'tekton.dev'
+ apiVersion: 'v1'
+
+
+ ...
+ apiVersion: rbac.authorization.k8s.io/v1
+ kind: ClusterRole
+ metadata:
+ name: backstage-read-only
+ rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods/log
+ verbs:
+ - get
+ - list
+ - watch
+ ...
+ - apiGroups:
+ - tekton.dev
+ resources:
+ - pipelineruns
+ - taskruns
+ verbs:
+ - get
+ - list
+----
+--
++
+You can use the prepared manifest for a read-only `ClusterRole`, which provides access for both Kubernetes plugin and Tekton plugin.
+
+* Add the following annotation to the entity's `catalog-info.yaml` file to identify whether an entity contains the Kubernetes resources:
++
+--
+[source,yaml]
+----
+annotations:
+ ...
+
+ backstage.io/kubernetes-id:
+----
+--
+
+* You can also add the `backstage.io/kubernetes-namespace` annotation to identify the Kubernetes resources using the defined namespace.
++
+--
+[source,yaml]
+----
+annotations:
+ ...
+
+ backstage.io/kubernetes-namespace:
+----
+--
+
+* Add the following annotation to the `catalog-info.yaml` file of the entity to enable the Tekton related features in RHDH. The value of the annotation identifies the name of the RHDH entity:
++
+--
+[source,yaml]
+----
+annotations:
+ ...
+
+ janus-idp.io/tekton :
+----
+--
+
+* Add a custom label selector, which RHDH uses to find the Kubernetes resources. The label selector takes precedence over the ID annotations.
++
+--
+[source,yaml]
+----
+annotations:
+ ...
+
+ backstage.io/kubernetes-label-selector: 'app=my-app,component=front-end'
+----
+--
+
+* Add the following label to the resources so that the Kubernetes plugin gets the Kubernetes resources from the requested entity:
++
+--
+[source,yaml]
+----
+labels:
+ ...
+
+ backstage.io/kubernetes-id:
+----
+--
++
+[NOTE]
+When you use the label selector, the mentioned labels must be present on the resource.
+
+.Procedure
+* The Tekton plugin is pre-loaded in RHDH with basic configuration properties. To enable it, set the disabled property to false as follows:
++
+--
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-tekton
+ disabled: false
+----
+--
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/tekton/tekton-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/tekton/tekton-plugin-readme.adoc
new file mode 100644
index 0000000000..010180df3b
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/tekton/tekton-plugin-readme.adoc
@@ -0,0 +1,167 @@
+[[installation-and-configuration-tekton]]
+= Installation and configuration of Tekton
+
+You can use the Tekton plugin to visualize the results of CI/CD pipeline runs on your Kubernetes or OpenShift clusters. The plugin allows users to visually see high level status of all associated tasks in the pipeline for their applications.
+
+== For administrators
+
+[[installing-tekton-plugin]]
+=== Installation
+
+.Prerequsites
+* You have installed and configured the `@backstage/plugin-kubernetes` and `@backstage/plugin-kubernetes-backend` dynamic plugins.
+//For more information about installing dynamic plugins, see xref:rhdh-installing-dynamic-plugins[].
+//Cannot xref across titles. Convert xref to a link.
+
+* You have configured the Kubernetes plugin to connect to the cluster using a `ServiceAccount`.
+
+* The `ClusterRole` must be granted for custom resources (PipelineRuns and TaskRuns) to the `ServiceAccount` accessing the cluster.
++
+[NOTE]
+If you have the RHDH Kubernetes plugin configured, then the `ClusterRole` is already granted.
+
+* To view the pod logs, you have granted permissions for `pods/log`.
+
+* You can use the following code to grant the `ClusterRole` for custom resources and pod logs:
++
+--
+[source,yaml]
+----
+kubernetes:
+ ...
+ customResources:
+ - group: 'tekton.dev'
+ apiVersion: 'v1'
+ plural: 'pipelineruns'
+ - group: 'tekton.dev'
+ apiVersion: 'v1'
+
+
+ ...
+ apiVersion: rbac.authorization.k8s.io/v1
+ kind: ClusterRole
+ metadata:
+ name: backstage-read-only
+ rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods/log
+ verbs:
+ - get
+ - list
+ - watch
+ ...
+ - apiGroups:
+ - tekton.dev
+ resources:
+ - pipelineruns
+ - taskruns
+ verbs:
+ - get
+ - list
+----
+--
++
+You can use the prepared manifest for a read-only `ClusterRole`, which provides access for both Kubernetes plugin and Tekton plugin.
+
+* Add the following annotation to the entity's `catalog-info.yaml` file to identify whether an entity contains the Kubernetes resources:
++
+--
+[source,yaml]
+----
+annotations:
+ ...
+
+ backstage.io/kubernetes-id:
+----
+--
+
+* You can also add the `backstage.io/kubernetes-namespace` annotation to identify the Kubernetes resources using the defined namespace.
++
+--
+[source,yaml]
+----
+annotations:
+ ...
+
+ backstage.io/kubernetes-namespace:
+----
+--
+
+* Add the following annotation to the `catalog-info.yaml` file of the entity to enable the Tekton related features in RHDH. The value of the annotation identifies the name of the RHDH entity:
++
+--
+[source,yaml]
+----
+annotations:
+ ...
+
+ janus-idp.io/tekton :
+----
+--
+
+* Add a custom label selector, which RHDH uses to find the Kubernetes resources. The label selector takes precedence over the ID annotations.
++
+--
+[source,yaml]
+----
+annotations:
+ ...
+
+ backstage.io/kubernetes-label-selector: 'app=my-app,component=front-end'
+----
+--
+
+* Add the following label to the resources so that the Kubernetes plugin gets the Kubernetes resources from the requested entity:
++
+--
+[source,yaml]
+----
+labels:
+ ...
+
+ backstage.io/kubernetes-id:
+----
+--
++
+[NOTE]
+When you use the label selector, the mentioned labels must be present on the resource.
+
+.Procedure
+* The Tekton plugin is pre-loaded in RHDH with basic configuration properties. To enable it, set the disabled property to false as follows:
++
+--
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-tekton
+ disabled: false
+----
+--
+
+== For users
+
+[[using-tekton-plugin]]
+=== Using the Tekton plugin in RHDH
+You can use the Tekton front-end plugin to view `PipelineRun` resources.
+
+.Prerequisites
+* You have installed the Red Hat Developer Hub (RHDH).
+* You have installed the Tekton plugin. For the installation process, see xref:installation-and-configuration-tekton[Installing and configuring the Tekton plugin].
+
+.Procedure
+. Open your RHDH application and select a component from the *Catalog* page.
+. Go to the *CI* tab.
++
+The *CI* tab displays the list of PipelineRun resources associated with a Kubernetes cluster. The list contains pipeline run details, such as *NAME*, *VULNERABILITIES*, *STATUS*, *TASK STATUS*, *STARTED*, and *DURATION*.
++
+image::rhdh-plugins-reference/tekton-plugin-pipeline.png[ci-cd-tab-tekton]
+
+. Click the expand row button besides PipelineRun name in the list to view the PipelineRun visualization. The pipeline run resource includes tasks to complete. When you hover the mouse pointer on a task card, you can view the steps to complete that particular task.
++
+image::rhdh-plugins-reference/tekton-plugin-pipeline-expand.png[ci-cd-tab-tekton]
diff --git a/artifacts/rhdh-plugins-reference/tekton/tekton-plugin-user.adoc b/artifacts/rhdh-plugins-reference/tekton/tekton-plugin-user.adoc
new file mode 100644
index 0000000000..ab5094488d
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/tekton/tekton-plugin-user.adoc
@@ -0,0 +1,22 @@
+[[installation-and-configuration-tekton]]
+= Using the Tekton plugin
+
+You can use the Tekton plugin to visualize the results of CI/CD pipeline runs on your Kubernetes or OpenShift clusters. The plugin allows users to visually see high level status of all associated tasks in the pipeline for their applications.
+
+You can use the Tekton front-end plugin to view `PipelineRun` resources.
+
+.Prerequisites
+* You have installed the Red Hat Developer Hub (RHDH).
+* You have installed the Tekton plugin. For the installation process, see xref:installation-and-configuration-tekton[Installing and configuring the Tekton plugin].
+
+.Procedure
+. Open your RHDH application and select a component from the *Catalog* page.
+. Go to the *CI* tab.
++
+The *CI* tab displays the list of PipelineRun resources associated with a Kubernetes cluster. The list contains pipeline run details, such as *NAME*, *VULNERABILITIES*, *STATUS*, *TASK STATUS*, *STARTED*, and *DURATION*.
++
+image::rhdh-plugins-reference/tekton-plugin-pipeline.png[ci-cd-tab-tekton]
+
+. Click the expand row button besides PipelineRun name in the list to view the PipelineRun visualization. The pipeline run resource includes tasks to complete. When you hover the mouse pointer on a task card, you can view the steps to complete that particular task.
++
+image::rhdh-plugins-reference/tekton-plugin-pipeline-expand.png[ci-cd-tab-tekton]
diff --git a/artifacts/rhdh-plugins-reference/topology/topology-install-dynamic-plugin.adoc b/artifacts/rhdh-plugins-reference/topology/topology-install-dynamic-plugin.adoc
new file mode 100644
index 0000000000..243b78b9a5
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/topology/topology-install-dynamic-plugin.adoc
@@ -0,0 +1,15 @@
+.Installation
+The Topology plugin is pre-loaded in {product-short} with basic configuration properties. To enable it, set the `disabled` property to `false` as follows:
+
+[source,yaml]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/janus-idp-backstage-plugin-topology
+ disabled: false
+----
+
+.Configuration
\ No newline at end of file
diff --git a/artifacts/rhdh-plugins-reference/topology/topology-plugin-admin.adoc b/artifacts/rhdh-plugins-reference/topology/topology-plugin-admin.adoc
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/artifacts/rhdh-plugins-reference/topology/topology-plugin-readme.adoc b/artifacts/rhdh-plugins-reference/topology/topology-plugin-readme.adoc
new file mode 100644
index 0000000000..57662a8897
--- /dev/null
+++ b/artifacts/rhdh-plugins-reference/topology/topology-plugin-readme.adoc
@@ -0,0 +1,412 @@
+= Topology
+
+The Topology plugin enables you to visualize the workloads such as Deployment, Job, Daemonset, Statefulset, CronJob, and Pods powering any service on the Kubernetes cluster.
+
+== For administrators
+
+=== Installation
+
+ifeval::[{doc-show-dynamic-content} == false]
+The Red Hat Plug-ins for Backstage (RHPIB) packages are hosted in a separate NPM registry, which is maintained by Red Hat. To use these packages, you must adjust your NPM configuration to pull the `@redhat` scoped packages:
+
+[source]
+----
+# update your .npmrc or .yarnrc file
+yarn config set "@redhat:registry" https://npm.registry.redhat.com
+# then pull a package
+yarn add @redhat/backstage-plugin-quay
+----
+
+For more information, see link:https://docs.npmjs.com/cli/v9/configuring-npm/npmrc[npm docs].
+
+Creating a `.npmrc` file ensures that all the packages are scoped under `@redhat` and are fetched from link:https://npm.registry.redhat.com/[Red Hat's NPM registry], while the rest dependencies remain sourced from other link:registry.npmjs.org[registry].
+
+Using this configuration, you can proceed with the installation of the individual packages.
+endif::[]
+.Prerequisites
+
+* The Kubernetes plugins including `@backstage/plugin-kubernetes` and `@backstage/plugin-kubernetes-backend` are installed and configured by following the https://backstage.io/docs/features/kubernetes/installation[installation] and https://backstage.io/docs/features/kubernetes/configuration[configuration] guides.
+* The Kubernetes plugin is configured and connects to the cluster using a `ServiceAccount`.
+* The https://backstage.io/docs/features/kubernetes/configuration#role-based-access-control[`ClusterRole`] must be granted to `ServiceAccount` accessing the cluster. If you have the {product-short} Kubernetes plugin configured, then the `ClusterRole` is already granted.
+* The following must be added in``customResources`` component in the https://backstage.io/docs/features/kubernetes/configuration#configuring-kubernetes-clusters[`app-config.yaml`] file to view the OpenShift route:
++
+--
+[source,yaml]
+----
+ kubernetes:
+ ...
+ customResources:
+ - group: 'route.openshift.io'
+ apiVersion: 'v1'
+ plural: 'routes'
+----
+
+Also, ensure that the route is granted a https://backstage.io/docs/features/kubernetes/configuration#role-based-access-control[`ClusterRole`]. You can use the following code to grant the `ClusterRole` to the route :
+
+[source,yaml]
+----
+ ...
+ apiVersion: rbac.authorization.k8s.io/v1
+ kind: ClusterRole
+ metadata:
+ name: backstage-read-only
+ rules:
+ ...
+ - apiGroups:
+ - route.openshift.io
+ resources:
+ - routes
+ verbs:
+ - get
+ - list
+
+----
+--
+
+* The following permission must be granted to the https://backstage.io/docs/features/kubernetes/configuration#role-based-access-control[`ClusterRole`] to be able to view the pod logs:
++
+--
+[source,yaml]
+----
+ apiVersion: rbac.authorization.k8s.io/v1
+ kind: ClusterRole
+ metadata:
+ name: backstage-read-only
+ rules:
+ ...
+ - apiGroups:
+ - ''
+ resources:
+ - pods
+ - pods/log
+ verbs:
+ - get
+ - list
+ - watch
+----
+--
+
+* The following code must be added in `customResources` component in the https://backstage.io/docs/features/kubernetes/configuration#configuring-kubernetes-clusters[`app-config.yaml`] file to view the Tekton PipelineRuns list in the side panel and to view the latest PipelineRun status in the Topology node decorator:
++
+--
+[source,yaml]
+----
+ kubernetes:
+ ...
+ customResources:
+ - group: 'tekton.dev'
+ apiVersion: 'v1beta1'
+ plural: 'pipelines'
+ - group: 'tekton.dev'
+ apiVersion: 'v1beta1'
+ plural: 'pipelineruns'
+ - group: 'tekton.dev'
+ apiVersion: 'v1beta1'
+ plural: 'taskruns'
+----
+
+Also, ensure that the Pipeline, PipelineRun, and TaskRun are granted a https://backstage.io/docs/features/kubernetes/configuration#role-based-access-control[`ClusterRole`]. You can use the following code to grant the `ClusterRole` to Pipeline, PipelineRun, and TaskRun:
+
+[source,yaml]
+----
+ apiVersion: rbac.authorization.k8s.io/v1
+ kind: ClusterRole
+ metadata:
+ name: backstage-read-only
+ rules:
+ ...
+ - apiGroups:
+ - tekton.dev
+ resources:
+ - pipelines
+ - pipelineruns
+ - taskruns
+ verbs:
+ - get
+ - list
+----
+--
+
+* The following configuration must be added in`customResources` component in the https://backstage.io/docs/features/kubernetes/configuration#configuring-kubernetes-clusters[`app-config.yaml`] file to view the edit code decorator:
++
+--
+[source,yaml]
+----
+ kubernetes:
+ ...
+ customResources:
+ - group: 'org.eclipse.che'
+ apiVersion: 'v2'
+ plural: 'checlusters'
+----
+
+Also, ensure that the `CheCluster` is granted a https://backstage.io/docs/features/kubernetes/configuration#role-based-access-control[`ClusterRole`] as shown in the following example code:
+
+[source,yaml]
+----
+ apiVersion: rbac.authorization.k8s.io/v1
+ kind: ClusterRole
+ metadata:
+ name: backstage-read-only
+ rules:
+ ...
+ - apiGroups:
+ - org.eclipse.che
+ resources:
+ - checlusters
+ verbs:
+ - get
+ - list
+----
+--
+
+* The following annotations are added to workload resources in the `deployment.yaml` file to navigate to the GitHub repository of the associated application using the edit code decorator:
++
+--
+[source,yaml]
+----
+annotations:
+ app.openshift.io/vcs-uri:
+----
+
+You can also add the following annotation to navigate to a specific branch:
+
+[source,yaml]
+----
+annotations:
+ app.openshift.io/vcs-ref:
+----
+
+If Red Hat OpenShift Dev Spaces (RHODS) is installed and configured and Git URL annotations are also added in the workload YAML file, then clicking on the edit code decorator redirects you to the RHODS instance. For more information about installing RHODS, see https://access.redhat.com/documentation/en-us/red_hat_openshift_dev_spaces/3.7/html/administration_guide/installing-devspaces[Administration guide] of RHODS.
+
+When you deploy your application using the OCP git import flow, then you do not need to add the labels as import flow to the workload YAML file. Otherwise, you would need to add the labels to the workload YAML file manually.
+
+The labels are not similar to `backstage.io/edit-url` annotations as the added labels point to the source file of catalog entity metadata and is applied to {product-short} catalog entity metadata YAML file, but not to the Kubernetes resources.
+
+You can also add the `app.openshift.io/edit-url` annotation that you want to access using the decorator.
+
+[TIP]
+====
+You can use the https://raw.githubusercontent.com/janus-idp/backstage-plugins/main/plugins/topology/manifests/clusterrole.yaml[prepared manifest for a read-only `ClusterRole`], which provides access for both Kubernetes and Topology plugin.
+====
+--
+
+* The following annotation is added to the entity's `catalog-info.yaml` file to identify whether an entitiy contains the Kubernetes resources:
++
+--
+[source,yaml]
+----
+annotations:
+ backstage.io/kubernetes-id:
+----
+
+The following label is added to the resources so that the Kubernetes plugin receives the Kubernetes resources from the requested entity:
+
+[source,yaml]
+----
+labels:
+ backstage.io/kubernetes-id: `
+----
+
+[NOTE]
+====
+
+When using the label selector, the mentioned labels must be present on the resource.
+====
+--
+
+* The `backstage.io/kubernetes-namespace` annotation is added as follows to identify that the Kubernetes resources are using the defined namespace:
++
+--
+[source,yaml]
+----
+annotations:
+ backstage.io/kubernetes-namespace:
+----
+
+If the `backstage.io/kubernetes-namespace` annotation is added to the `catalog-info.yaml` file, then the RHODS instance is not accessible using the edit code decorator.
+
+To retrieve the instance URL, CheCluster Custom Resource (CR) is required. The instance URL is not retrieved if the namespace annotation value is different from `openshift-devspaces` as CheCluster CR is created in `openshift-devspaces` namespace.
+--
+
+* A custom label selector is added, which {product-short} uses to find the Kubernetes resources. The label selector takes precedence over the ID annotations. For example:
++
+--
+[source,yaml]
+----
+annotations:
+ backstage.io/kubernetes-label-selector: 'app=my-app,component=front-end'
+----
+
+If you have multiple entities while RHODS is configured and want multiple entities to support the edit code decorator that redirects to the RHODS instance, you can add the `backstage.io/kubernetes-label-selector` annotation to the `catalog-info.yaml` file for each entity as follows:
+
+[source,yaml]
+----
+annotations:
+ backstage.io/kubernetes-label-selector: 'component in (,che)'
+----
+
+If you are using the previous custom label selector, then make sure that you add the following labels to your resources so that the Kubernetes plugin receives the Kubernetes resources from the requested entity:
+
+[source,yaml]
+----
+labels:
+ component: che # add this label to your che cluster instance
+----
+
+[source,yaml]
+----
+labels:
+ component: # add this label to the other resources associated with your entity
+----
+
+You can also write your own custom query for the label selector with unique labels to differentiate your entities. However, you need to ensure that you add those labels to the resources associated with your entities including your CheCluster instance.
+--
+
+* The following label is added to workload resources in the `deployment.yaml` file to display runtime icon in the topology nodes:
++
+--
+[source,yaml]
+----
+labels:
+ app.openshift.io/runtime:
+----
+
+Alternatively, you can include the following label to display the runtime icon:
+
+[source,yaml]
+----
+labels:
+ app.kubernetes.io/name:
+----
+
+The `` parameter in the previous example label supports the following values:
+
+* `django`
+* `dotnet`
+* `drupal`
+* `go-gopher`
+* `golang`
+* `grails`
+* `jboss`
+* `jruby`
+* `js`
+* `nginx`
+* `nodejs`
+* `openjdk`
+* `perl`
+* `phalcon`
+* `php`
+* `python`
+* `quarkus`
+* `rails`
+* `redis`
+* `rh-spring-boot`
+* `rust`
+* `java`
+* `rh-openjdk`
+* `ruby`
+* `spring`
+* `spring-boot`
+
+Any other value for `` parameter results in icons not being rendered for the node.
+--
+
+* The following label is added to display the workload resources such as Deployments and Pods in a visual group:
++
+--
+[source,yaml]
+----
+ ```yaml title="catalog-info.yaml"
+ labels:
+ app.kubernetes.io/part-of:
+ ```
+----
+--
+
+* The following annotation is added to display the workload resources such as Deployments and Pods with a visual connector:
++
+--
+[source]
+----
+ ```yaml title="catalog-info.yaml"
+ annotations:
+ app.openshift.io/connects-to: '[{"apiVersion": ,"kind": ,"name": }]'
+ ```
+----
+
+For more information about the labels and annotations, see https://github.com/redhat-developer/app-labels/blob/master/labels-annotation-for-openshift.adoc[Guidelines for labels and annotations for OpenShift applications].
+--
+
+.Procedure
+ifeval::[{doc-show-dynamic-content} == true]
+include::../../../artifacts/rhdh-plugins-reference/topology/topology-install-dynamic-plugin.adoc[leveloffset=+2]
+endif::[]
+
+ifeval::[{doc-show-dynamic-content} == false]
+. Install the Topology plugin using the following command:
++
+--
+[source,console]
+----
+yarn workspace app add @redhat/backstage-plugin-topology
+----
+--
+
+. Enable *TOPOLOGY* tab in `packages/app/src/components/catalog/EntityPage.tsx`:
++
+--
+[source]
+----
+ ```tsx title="packages/app/src/components/catalog/EntityPage.tsx"
+ /* highlight-add-next-line */
+ import { TopologyPage } from '@redhat/backstage-plugin-topology';
+
+ const serviceEntityPage = (
+
+ {/* ... */}
+ {/* highlight-add-start */}
+
+
+
+ {/* highlight-add-end */}
+
+ );
+ ```
+----
+--
+endif::[]
+
+== For users
+
+=== Using the Topology plugin in {product-short}
+
+Topology is a front-end plugin that enables you to view the workloads as nodes that power any service on the Kubernetes cluster.
+
+.Prerequisites
+
+* Your {product-short} application is installed and running.
+* You have installed the Topology plugin. For the installation process, see <>.
+
+.Procedure
+
+. Open your {product-short} application and select a component from the *Catalog* page.
+. Go to the *TOPOLOGY* tab and you can view the workloads such as Deployments, Pods as nodes.
++
+image::topology-tab-user1.png[topology-tab]
+
+. Select a node and a pop-up appears on the right side, which contains two tabs: *Details* and *Resources*.
++
+--
+The *Details* and *Resources* tab contain the associated information and resources of the node.
+
+image::topology-tab-user2.png[topology-tab-details]
+--
+
+. Click on the *Open URL* button on the top of a node.
++
+--
+image::topology-tab-user3.png[topology-tab-open-url]
+
+When you click on the open URL button, it allows you to access the associated *Ingresses* and runs your application in a new tab.
+--
diff --git a/artifacts/rhdh-plugins-reference/topology/topology-plugin-user.adoc b/artifacts/rhdh-plugins-reference/topology/topology-plugin-user.adoc
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/artifacts/snip-conscious-language.adoc b/artifacts/snip-conscious-language.adoc
new file mode 100644
index 0000000000..e8515c6a85
--- /dev/null
+++ b/artifacts/snip-conscious-language.adoc
@@ -0,0 +1,5 @@
+[preface]
+[id='snip-conscious-language_{context}']
+= Making open source more inclusive
+
+Red Hat is committed to replacing problematic language in our code, documentation, and web properties. We are beginning with these four terms: master, slave, blacklist, and whitelist. Because of the enormity of this endeavor, these changes will be implemented gradually over several upcoming releases. For more details, see https://www.redhat.com/en/blog/making-open-source-more-inclusive-eradicating-problematic-language[_our CTO Chris Wright's message_].
diff --git a/artifacts/snip-customer-support-info.adoc b/artifacts/snip-customer-support-info.adoc
new file mode 100644
index 0000000000..4143e8b937
--- /dev/null
+++ b/artifacts/snip-customer-support-info.adoc
@@ -0,0 +1,8 @@
+[preface]
+[id='snip-customer-support-info_{context}']
+= Red Hat Developer Hub support
+
+If you experience difficulty with a procedure described in this documentation, visit the http://access.redhat.com[Red Hat Customer Portal]. You can use the Red Hat Customer Portal for the following purposes:
+
+* To search or browse through the Red Hat Knowledgebase of technical support articles about Red Hat products.
+* To create a https://access.redhat.com/support/cases/#/case/new/get-support?caseCreate=true[support case] for {company-name} Global Support Services (GSS). For support case creation, select *{product}* as the product and select the appropriate product version. For detailed information about supported platforms, see link:{release-notes-url}#con-release-notes-overview.adoc[Supported Platforms] and the link:https://access.redhat.com/support/policy/updates/developerhub[{product} Life Cycle].
\ No newline at end of file
diff --git a/artifacts/snip-dynamic-plugins-support.adoc b/artifacts/snip-dynamic-plugins-support.adoc
new file mode 100644
index 0000000000..0b70b98922
--- /dev/null
+++ b/artifacts/snip-dynamic-plugins-support.adoc
@@ -0,0 +1,12 @@
+[id='snip-dynamic-plugins-support_{context}']
+
+= Technology Preview plugins
+
+[IMPORTANT]
+====
+{product} includes a select number of Technology Preview plugins, available for customers to configure and enable. These plugins are provided with support scoped per Technical Preview terms, might not be functionally complete, and {company-name} does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+// Additional details on how Red Hat provides support for bundled community dynamic plugins are available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
diff --git a/artifacts/snip-technology-preview.adoc b/artifacts/snip-technology-preview.adoc
new file mode 100644
index 0000000000..e94b591ef7
--- /dev/null
+++ b/artifacts/snip-technology-preview.adoc
@@ -0,0 +1,6 @@
+[IMPORTANT]
+====
+These features are for Technology Preview only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+====
diff --git a/assemblies/assembly-add-custom-app-file-openshift.adoc b/assemblies/assembly-add-custom-app-file-openshift.adoc
new file mode 100644
index 0000000000..21978f413c
--- /dev/null
+++ b/assemblies/assembly-add-custom-app-file-openshift.adoc
@@ -0,0 +1,25 @@
+[id='assembly-add-custom-app-file-openshift_{context}']
+= Adding a custom application configuration file to {ocp-brand-name}
+
+To access the {product}, you must add a custom application configuration file to {ocp-brand-name}. In {ocp-short}, you can use the following content as a base template to create a ConfigMap named `app-config-rhdh`:
+
+[source,yaml,subs="attributes+"]
+----
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: app-config-rhdh
+data:
+ app-config-rhdh.yaml: |
+ app:
+ title: {product}
+----
+
+You can add the custom application configuration file to {ocp-short} in one of the following ways:
+
+* The {product} Operator
+* The {product} Helm chart
+
+include::modules/getting-started/proc-add-custom-app-file-openshift-helm.adoc[leveloffset=+1]
+
+include::modules/installation/proc-add-custom-app-config-file-ocp-operator.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-admin-templates.adoc b/assemblies/assembly-admin-templates.adoc
new file mode 100644
index 0000000000..e200a047a5
--- /dev/null
+++ b/assemblies/assembly-admin-templates.adoc
@@ -0,0 +1,25 @@
+:_mod-docs-content-type: ASSEMBLY
+[id="assembly-admin-templates"]
+= Managing templates
+:context: assembly-admin-templates
+
+toc::[]
+
+A template is a form composed of different UI fields that is defined in a YAML file. Templates include _actions_, which are steps that are executed in sequential order and can be executed conditionally.
+
+You can use templates to easily create {product} components, and then publish these components to different locations, such as the {product} software catalog, or repositories in GitHub or GitLab.
+
+include::modules/templates/proc-creating-templates.adoc[leveloffset=+1]
+include::modules/templates/ref-creating-templates.adoc[leveloffset=+1]
+
+[role="_additional-resources"]
+.Additional resources
+* link:https://backstage.io/docs/features/software-templates/writing-templates[Backstage documentation - Writing Templates]
+* link:https://backstage.io/docs/features/software-templates/builtin-actions[Backstage documentation - Builtin actions]
+* link:https://backstage.io/docs/features/software-templates/writing-custom-actions[Backstage documentation - Writing Custom Actions]
+
+include::modules/templates/proc-adding-templates.adoc[leveloffset=+1]
+
+[role="_additional-resources"]
+.Additional resources
+* link:{authentication-book-url}#assembly-auth-provider-github[Enabling the GitHub authentication provider]
diff --git a/assemblies/assembly-audit-log.adoc b/assemblies/assembly-audit-log.adoc
new file mode 100644
index 0000000000..f70f4e64ec
--- /dev/null
+++ b/assemblies/assembly-audit-log.adoc
@@ -0,0 +1,46 @@
+[id="assembly-audit-log"]
+= Audit logs in {product}
+:context: assembly-audit-log
+
+Audit logs are a chronological set of records documenting the user activities, system events, and data changes that affect your {product} users, administrators, or components. Administrators can view {product-short} audit logs in the {ocp-short} web console to monitor scaffolder events, changes to the RBAC system, and changes to the Catalog database. Audit logs include the following information:
+
+* Name of the audited event
+* Actor that triggered the audited event, for example, terminal, port, IP address, or hostname
+* Event metadata, for example, date, time
+* Event status, for example, `success`, `failure`
+* Severity levels, for example, `info`, `debug`, `warn`, `error`
+
+You can use the information in the audit log to achieve the following goals:
+
+Enhance security::
+Trace activities, including those initiated by automated systems and software templates, back to their source. Know when software templates are executed, as well as the details of application and component installations, updates, configuration changes, and removals.
+
+Automate compliance::
+Use streamlined processes to view log data for specified points in time for auditing purposes or continuous compliance maintenance.
+
+Debug issues::
+Use access records and activity details to fix issues with software templates or plugins.
+
+[NOTE]
+====
+Audit logs are not forwarded to the internal log store by default because this does not provide secure storage. You are responsible for ensuring that the system to which you forward audit logs is compliant with your organizational and governmental regulations, and is properly secured.
+====
+
+[role="_additional-resources"]
+.Additional resources
+
+* For more information about logging in {ocp-short}, see link:https://docs.openshift.com/container-platform/latest/observability/logging/cluster-logging.html[About Logging]
+* For a complete list of fields that a {product-short} audit log can include, see xref:ref-audit-log-fields.adoc_{context}[]
+* For a list of scaffolder events that a {product-short} audit log can include, see xref:ref-audit-log-scaffolder-events.adoc_{context}[]
+
+include::modules/getting-started/con-audit-log-config.adoc[leveloffset=+1]
+
+include::modules/getting-started/proc-audit-log-view.adoc[leveloffset=+1]
+
+include::modules/getting-started/ref-audit-log-fields.adoc[leveloffset=+2]
+
+include::modules/getting-started/ref-audit-log-scaffolder-events.adoc[leveloffset=+2]
+
+include::modules/getting-started/ref-audit-log-catalog-events.adoc[leveloffset=+2]
+
+include::modules/getting-started/ref-audit-log-file-rotation-overview.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-authenticating-with-github.adoc b/assemblies/assembly-authenticating-with-github.adoc
new file mode 100644
index 0000000000..70d1c5a361
--- /dev/null
+++ b/assemblies/assembly-authenticating-with-github.adoc
@@ -0,0 +1,13 @@
+[id="assembly-auth-provider-github"]
+= Enabling the GitHub authentication provider
+
+To authenticate users with GitHub or GitHub Enterprise:
+
+. xref:enabling-authentication-with-github[Enable the GitHub authentication provider in {product-short}].
+. xref:provisioning-users-from-github-to-the-software-catalog[Provision users from GitHub to the software catalog].
+
+include::modules/authentication/proc-enabling-authentication-with-github.adoc[leveloffset=+1]
+
+
+include::modules/authentication/proc-provisioning-users-from-github-to-the-software-catalog.adoc[leveloffset=+1]
+
diff --git a/assemblies/assembly-authenticating-with-microsoft-azure.adoc b/assemblies/assembly-authenticating-with-microsoft-azure.adoc
new file mode 100644
index 0000000000..d575ae393e
--- /dev/null
+++ b/assemblies/assembly-authenticating-with-microsoft-azure.adoc
@@ -0,0 +1,13 @@
+[id="assembly-authenticating-with-microsoft-azure"]
+= Authentication with Microsoft Azure
+
+To authenticate users with Microsoft Azure:
+
+. xref:enabling-authentication-with-microsoft-azure[Enable authentication with Microsoft Azure].
+. xref:provisioning-users-from-microsoft-azure-to-the-software-catalog[Provision users from Microsoft Azure to the software catalog].
+
+include::modules/authentication/proc-enabling-authentication-with-microsoft-azure.adoc[leveloffset=+1]
+
+
+include::modules/authentication/proc-provisioning-users-from-microsoft-azure-to-the-software-catalog.adoc[leveloffset=+1]
+
diff --git a/assemblies/assembly-authenticating-with-rhsso.adoc b/assemblies/assembly-authenticating-with-rhsso.adoc
new file mode 100644
index 0000000000..d3d5b1c95c
--- /dev/null
+++ b/assemblies/assembly-authenticating-with-rhsso.adoc
@@ -0,0 +1,13 @@
+[id="assembly-authenticating-with-rhsso"]
+= Authenticating with Red Hat Single Sign-On (RHSSO)
+
+To authenticate users with Red Hat Single Sign-On (RHSSO):
+
+. xref:enabling-authentication-with-rhsso[Enable the OpenID Connect (OIDC) authentication provider in RHDH].
+. xref:provisioning-users-from-rhsso-to-the-software-catalog[Provision users from Red Hat Single-Sign On (RHSSO) to the software catalog].
+
+include::modules/authentication/proc-enabling-authentication-with-rhsso.adoc[leveloffset=+1]
+
+include::modules/authentication/proc-provisioning-users-from-rhsso-to-the-software-catalog.adoc[leveloffset=+1]
+
+include::modules/authentication/proc-creating-a-custom-transformer-to-provision-users-from-rhsso-to-the-software-catalog.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-authenticating-with-the-guest-user.adoc b/assemblies/assembly-authenticating-with-the-guest-user.adoc
new file mode 100644
index 0000000000..2e87fe7882
--- /dev/null
+++ b/assemblies/assembly-authenticating-with-the-guest-user.adoc
@@ -0,0 +1,12 @@
+:_mod-docs-content-type: PROCEDURE
+[id="authenticating-with-the-guest-user_{context}"]
+= Authenticating with the Guest user
+
+To explore {product-short} features, you can skip configuring authentication and authorization.
+You can configure {product-short} to log in as a Guest user and access {product-short} features.
+
+include::modules/authentication/proc-authenticationg-with-the-guest-user-on-an-operator-based-installation.adoc[leveloffset=+1]
+
+
+include::modules/authentication/proc-authenticationg-with-the-guest-user-on-a-helm-based-installation.adoc[leveloffset=+1]
+
diff --git a/assemblies/assembly-bulk-importing-from-github.adoc b/assemblies/assembly-bulk-importing-from-github.adoc
new file mode 100644
index 0000000000..0641acf589
--- /dev/null
+++ b/assemblies/assembly-bulk-importing-from-github.adoc
@@ -0,0 +1,15 @@
+[id="bulk-importing-github-repositories"]
+= Bulk importing GitHub repositories
+
+include::{docdir}/artifacts/snip-technology-preview.adoc[]
+
+{product} can automate GitHub repositories onboarding and track their import status.
+
+include::modules/importing-repositories/procedure-enabling-the-bulk-import-from-github-feature.adoc[leveloffset=+1]
+
+include::modules/importing-repositories/procedure-importing-multiple-repositories-from-github.adoc[leveloffset=+1]
+
+include::modules/importing-repositories/procedure-managing-the-imported-repository-list.adoc[leveloffset=+1]
+
+include::modules/importing-repositories/procedure-understanding-bulk-import-audit-logs.adoc[leveloffset=+1]
+
diff --git a/assemblies/assembly-configuring-authorization-in-rhdh.adoc b/assemblies/assembly-configuring-authorization-in-rhdh.adoc
new file mode 100644
index 0000000000..6089d3cc52
--- /dev/null
+++ b/assemblies/assembly-configuring-authorization-in-rhdh.adoc
@@ -0,0 +1,56 @@
+[id='configuring-authorization-in-rhdh']
+= Configuring authorization in {product}
+
+include::modules/authorization/con-rbac-overview.adoc[leveloffset=+1]
+
+
+include::modules/authorization/ref-rbac-permission-policies.adoc[leveloffset=+1]
+
+
+include::modules/authorization/con-rbac-config-permission-policies.adoc[leveloffset=+2]
+
+
+include::modules/authorization/con-rbac-config-permission-policies-admin.adoc[leveloffset=+3]
+
+
+include::modules/authorization/con-rbac-config-permission-policies-external-file.adoc[leveloffset=+3]
+
+include::modules/authorization/proc-mounting-the-policy-csv-file-using-the-operator.adoc[leveloffset=+4]
+
+include::modules/authorization/proc-mounting-the-policy-csv-file-using-helm.adoc[leveloffset=+4]
+
+
+include::modules/authorization/con-rbac-conditional-policies-rhdh.adoc[leveloffset=+1]
+
+
+include::modules/authorization/ref-rbac-conditional-policy-definition.adoc[leveloffset=+2]
+
+
+include::modules/authorization/proc-rbac-config-conditional-policy-file.adoc[leveloffset=+2]
+
+
+include::modules/authorization/proc-rbac-ui-manage-roles.adoc[leveloffset=+1]
+
+
+include::modules/authorization/proc-rbac-ui-create-role.adoc[leveloffset=+2]
+
+
+include::modules/authorization/proc-rbac-ui-edit-role.adoc[leveloffset=+2]
+
+
+include::modules/authorization/proc-rbac-ui-delete-role.adoc[leveloffset=+2]
+
+
+include::modules/authorization/con-user-stats-rhdh.adoc[leveloffset=+1]
+
+
+include::modules/authorization/proc-download-user-stats-rhdh.adoc[leveloffset=+2]
+
+
+include::modules/authorization/con-rbac-rest-api.adoc[leveloffset=+1]
+
+
+include::modules/authorization/proc-rbac-send-request-rbac-rest-api.adoc[leveloffset=+2]
+
+
+include::modules/authorization/ref-rbac-rest-api-endpoints.adoc[leveloffset=+2]
diff --git a/assemblies/assembly-configuring-external-postgresql-databases.adoc b/assemblies/assembly-configuring-external-postgresql-databases.adoc
new file mode 100644
index 0000000000..3f63696dbf
--- /dev/null
+++ b/assemblies/assembly-configuring-external-postgresql-databases.adoc
@@ -0,0 +1,21 @@
+[id="assembly-configuring-external-postgresql-databases"]
+= Configuring external PostgreSQL databases
+
+As an administrator, you can configure and use external PostgreSQL databases in {product}. You can use a PostgreSQL certificate file to configure an external PostgreSQL instance using the Operator or Helm Chart.
+
+[NOTE]
+====
+{product-short} supports only configuring external PostgreSQL databases. You can perform maintenance activities, such as backing up your data or configuring high availability (HA) for the external PostgreSQL databases.
+
+Also, configuring an external PostgreSQL instance by using the {product} Operator or Helm Chart is not intended for production use.
+====
+
+
+include::modules/admin/proc-configuring-postgresql-instance-using-operator.adoc[leveloffset=+1]
+
+include::modules/admin/proc-configuring-postgresql-instance-using-helm.adoc[leveloffset=+1]
+
+include::modules/admin/proc-migrating-databases-to-an-external-server.adoc[leveloffset=+1]
+
+
+
diff --git a/assemblies/assembly-customize-rhdh-theme.adoc b/assemblies/assembly-customize-rhdh-theme.adoc
new file mode 100644
index 0000000000..37c87a0669
--- /dev/null
+++ b/assemblies/assembly-customize-rhdh-theme.adoc
@@ -0,0 +1,42 @@
+:_mod-docs-content-type: ASSEMBLY
+[id="assembly-customize-rhdh-theme"]
+= Customizing the appearance of your {product} instance
+:context: assembly-customize-rhdh-theme
+
+The following default theme configurations are available for {product}:
+
+The {product} theme:: Default theme configurations to make your developer portal look like a standard {product} instance. For more information, see xref:ref-customize-rhdh-default-rhdh_{context}[]
+
+The Backstage theme:: Default theme configurations to make your developer portal look like a standard Backstage instance. For more information, see xref:ref-customize-rhdh-default-backstage_{context}[]
+
+You can change or disable particular parameters in a default theme or create a fully customized theme by modifying the `app-config-rhdh.yaml` file. From the the `app-config-rhdh.yaml` file, you can customize common theme components, including the following:
+
+* Company name and logo
+* Font color, size, and style of text in paragraphs, headings, headers, and buttons
+* Header color, gradient, and shape
+* Button color
+* Navigation indicator color
+
+You can also customize some components from the {product-short} GUI, such as the theme mode (*Light Theme*, *Dark Theme*, or *Auto*).
+
+include::modules/customization/proc-customize-rhdh-theme-mode.adoc[leveloffset=+1]
+
+include::modules/customization/proc-customize-rhdh-branding-logo.adoc[leveloffset=+1]
+
+//include::modules/customization/proc-customize-rhdh-sidebar-logo.adoc[leveloffset=+1]//commented since the section has been merged with proc-customize-rhdh-branding-logo.adoc in PR #514
+
+include::modules/customization/proc-customize-rhdh-sidebar-menuitems.adoc[leveloffset=+1]
+
+include::modules/customization/proc-customize-rhdh-tab-tooltip.adoc[leveloffset=+1]
+
+include::modules/customization/proc-customize-rhdh-palette.adoc[leveloffset=+1]
+
+include::modules/customization/proc-customize-rhdh-page-theme.adoc[leveloffset=+1]
+
+include::modules/customization/proc-customize-rhdh-font.adoc[leveloffset=+1]
+
+include::modules/customization/ref-customize-rhdh-default-rhdh.adoc[leveloffset=+1]
+
+include::modules/customization/ref-customize-rhdh-default-backstage.adoc[leveloffset=+1]
+
+include::modules/customization/ref-customize-rhdh-custom-components.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-enabling-authentication.adoc b/assemblies/assembly-enabling-authentication.adoc
new file mode 100644
index 0000000000..7d5308b51d
--- /dev/null
+++ b/assemblies/assembly-enabling-authentication.adoc
@@ -0,0 +1,63 @@
+[id='enabling-authentication']
+= Enabling authentication in {product}
+
+Depending on your organization's security policies, you might require to identify and authorize users before giving them access to resources, such as {product}.
+
+In {product-short}, authentication and authorization are two separate processes:
+
+. Authentication defines the user identity, and passes on this information to {product-short}.
+Read the following chapters to configure authentication in {product-short}.
+
+. Authorization defines what the authenticated identity can access or do in {product-short}.
+See link:{authorization-book-url}[{authorization-book-title}].
+
+[TIP]
+.Not recommended for production
+====
+To explore {product-short} features, you can enable the guest user to skip configuring authentication and authorization, log in as the guest user, and access all the features.
+====
+
+The authentication system in {product-short} is handled by external authentication providers.
+
+{product-short} supports following authentication providers:
+
+* Red Hat Single-Sign On (RHSSO)
+* GitHub
+* Microsoft Azure
+
+To identify users in {product-short}, configure:
+
+* One (and only one) authentication provider for sign-in and identification.
+* Optionally, additional authentication providers for identification, to add more information to the user identity, or enable access to additional external resources.
+
+For each authentication provider, set up the shared secret that the authentication provider and {product-short} require to communicate, first in the authentication provider, then in {product-short}.
+
+{product-short} stores user identity information in the {product-short} software catalog.
+
+[TIP]
+.Not recommended for production
+====
+To explore the authentication system and use {product-short} without authorization policies, you can bypass the {product-short} software catalog and start using {product-short} without provisioning the {product-short} software catalog.
+====
+
+To get, store, and update additional user information, such as group or team ownership, with the intention to use this data to define authorization policies, provision users and groups in the {product-short} software catalog.
+
+[IMPORTANT]
+====
+{product-short} uses a one-way synchronization system to provision users and groups from your authentication system to the {product-short} software catalog.
+Therefore, deleting users and groups by using {product-short} Web UI or REST API might have unintended consequences.
+====
+
+
+
+include::assembly-authenticating-with-the-guest-user.adoc[leveloffset=+1]
+
+
+include::assembly-authenticating-with-rhsso.adoc[leveloffset=+1]
+
+
+include::assembly-authenticating-with-github.adoc[leveloffset=+1]
+
+
+include::assembly-authenticating-with-microsoft-azure.adoc[leveloffset=+1]
+
diff --git a/assemblies/assembly-install-rhdh-ocp-helm.adoc b/assemblies/assembly-install-rhdh-ocp-helm.adoc
new file mode 100644
index 0000000000..662d44a650
--- /dev/null
+++ b/assemblies/assembly-install-rhdh-ocp-helm.adoc
@@ -0,0 +1,13 @@
+:_mod-docs-content-type: ASSEMBLY
+[id="assembly-install-rhdh-ocp-helm"]
+= Installing {product} on {ocp-short} with the Helm chart
+:context: assembly-install-rhdh-ocp-helm
+
+You can install {product} on {ocp-short} by using the Helm chart with one of the following methods:
+
+* The {ocp-short} console
+* The Helm CLI
+
+include::modules/installation/proc-install-rhdh-ocp-helm-gui.adoc[leveloffset=+1]
+
+include::modules/installation/proc-install-rhdh-ocp-helm-cli.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-install-rhdh-ocp-operator.adoc b/assemblies/assembly-install-rhdh-ocp-operator.adoc
new file mode 100644
index 0000000000..c02c4b2819
--- /dev/null
+++ b/assemblies/assembly-install-rhdh-ocp-operator.adoc
@@ -0,0 +1,10 @@
+:_mod-docs-content-type: ASSEMBLY
+[id="assembly-install-rhdh-ocp-operator"]
+= Installing {product} on {ocp-short} with the Operator
+:context: assembly-install-rhdh-ocp-operator
+
+You can install {product} on {ocp-short} by using the {product} Operator in the {ocp-short} console.
+
+include::modules/installation/proc-install-operator.adoc[leveloffset=+1]
+
+include::modules/installation/proc-install-rhdh-ocp-operator.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-install-rhdh-osd-gcp.adoc b/assemblies/assembly-install-rhdh-osd-gcp.adoc
new file mode 100644
index 0000000000..951bc0c564
--- /dev/null
+++ b/assemblies/assembly-install-rhdh-osd-gcp.adoc
@@ -0,0 +1,15 @@
+[id="assembly-install-rhdh-osd-gcp"]
+= Installing {product} on {osd-short} on {gcp-brand-name}
+:context: assembly-install-rhdh-osd-gcp
+
+You can install {product-short} on {osd-short} on {gcp-brand-name} ({gcp-short}) using one of the following methods:
+
+* The {product} Operator
+* The {product} Helm chart
+
+// Operator procedure
+include::modules/installation/proc-install-rhdh-osd-gcp-operator.adoc[leveloffset=+1]
+
+// Helm procedure
+include::modules/installation/proc-install-rhdh-osd-gcp-helm.adoc[leveloffset=+1]
+
diff --git a/assemblies/assembly-release-notes-breaking-changes.adoc b/assemblies/assembly-release-notes-breaking-changes.adoc
new file mode 100644
index 0000000000..32ccedc406
--- /dev/null
+++ b/assemblies/assembly-release-notes-breaking-changes.adoc
@@ -0,0 +1,20 @@
+:_content-type: ASSEMBLY
+[id="breaking-changes"]
+= Breaking changes
+
+This section lists breaking changes in {product} {product-version}.
+
+
+include::modules/release-notes/snip-removed-functionality-rhidp-3048.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-removed-functionality-rhidp-3074.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-removed-functionality-rhidp-3187.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-removed-functionality-rhidp-4293.adoc[leveloffset=+1]
+
+
+
diff --git a/assemblies/assembly-release-notes-deprecated-functionalities.adoc b/assemblies/assembly-release-notes-deprecated-functionalities.adoc
new file mode 100644
index 0000000000..9b960772e9
--- /dev/null
+++ b/assemblies/assembly-release-notes-deprecated-functionalities.adoc
@@ -0,0 +1,11 @@
+:_content-type: ASSEMBLY
+[id="deprecated-functionalities"]
+= Deprecated functionalities
+
+This section lists deprecated functionalities in {product} {product-version}.
+
+
+include::modules/release-notes/snip-deprecated-functionality-rhidp-1138.adoc[leveloffset=+1]
+
+
+
diff --git a/assemblies/assembly-release-notes-fixed-issues.adoc b/assemblies/assembly-release-notes-fixed-issues.adoc
new file mode 100644
index 0000000000..4462772088
--- /dev/null
+++ b/assemblies/assembly-release-notes-fixed-issues.adoc
@@ -0,0 +1,71 @@
+:_content-type: ASSEMBLY
+[id="fixed-issues"]
+= Fixed issues
+
+This section lists issues fixed in {product} {product-version}.
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-1334.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-2139.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-2374.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-2412.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-2438.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-2529.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-2716.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-2728.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3159.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3217.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3260.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3458.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3471.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3580.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3601.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3612.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3735.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-3896.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-4013.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-4046.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-bug-fix-rhidp-4200.adoc[leveloffset=+1]
+
+
+
diff --git a/assemblies/assembly-release-notes-fixed-security-issues.adoc b/assemblies/assembly-release-notes-fixed-security-issues.adoc
new file mode 100644
index 0000000000..a741a16d1a
--- /dev/null
+++ b/assemblies/assembly-release-notes-fixed-security-issues.adoc
@@ -0,0 +1,12 @@
+:_content-type: ASSEMBLY
+[id="fixed-security-issues"]
+= Fixed security issues
+
+This section lists security issues fixed in {product} {product-version}.
+
+== {product} {product-bundle-version}
+
+include::modules/release-notes/snip-fixed-security-issues-in-product-1.3.0.adoc[leveloffset=+2]
+
+include::modules/release-notes/snip-fixed-security-issues-in-rpm-1.3.0.adoc[leveloffset=+2]
+
diff --git a/assemblies/assembly-release-notes-known-issues.adoc b/assemblies/assembly-release-notes-known-issues.adoc
new file mode 100644
index 0000000000..244af1c2fe
--- /dev/null
+++ b/assemblies/assembly-release-notes-known-issues.adoc
@@ -0,0 +1,20 @@
+:_content-type: ASSEMBLY
+[id="known-issues"]
+= Known issues
+
+This section lists known issues in {product} {product-version}.
+
+
+include::modules/release-notes/snip-known-issue-rhidp-4378.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-known-issue-rhidp-4069.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-known-issue-rhidp-4067.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-known-issue-rhidp-3931.adoc[leveloffset=+1]
+
+
+
diff --git a/assemblies/assembly-release-notes-new-features.adoc b/assemblies/assembly-release-notes-new-features.adoc
new file mode 100644
index 0000000000..89161bc467
--- /dev/null
+++ b/assemblies/assembly-release-notes-new-features.adoc
@@ -0,0 +1,68 @@
+:_content-type: ASSEMBLY
+[id="new-features"]
+= New features
+
+This section highlights new features in {product} {product-version}.
+
+
+include::modules/release-notes/snip-feature-rhidp-2232.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-feature-rhidp-2341.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-2615.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-feature-rhidp-2643.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-feature-rhidp-2644.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-2695.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-2723.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-2736.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-2768.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-2790.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-2818.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-feature-rhidp-2865.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-feature-rhidp-2888.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-feature-rhidp-2907.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-3064.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-3125.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-feature-rhidp-3177.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-feature-rhidp-3569.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-feature-rhidp-3666.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-enhancement-rhidp-3826.adoc[leveloffset=+1]
+
+
+
diff --git a/assemblies/assembly-release-notes-technology-preview.adoc b/assemblies/assembly-release-notes-technology-preview.adoc
new file mode 100644
index 0000000000..b3fab28c45
--- /dev/null
+++ b/assemblies/assembly-release-notes-technology-preview.adoc
@@ -0,0 +1,22 @@
+:_content-type: ASSEMBLY
+[id="technology-preview"]
+= Technology Preview
+
+This section lists Technology Preview features in {product} {product-version}.
+
+[IMPORTANT]
+====
+Technology Preview features provide early access to upcoming product innovations, enabling you to test functionality and provide feedback during the development process.
+However, these features are not fully supported under Red Hat Subscription Level Agreements, may not be functionally complete, and are not intended for production use.
+As Red Hat considers making future iterations of Technology Preview features generally available, we will attempt to resolve any issues that customers experience when using these features.
+See: link:https://access.redhat.com/support/offerings/techpreview/[Technology Preview support scope].
+====
+
+
+include::modules/release-notes/snip-technology-preview-rhidp-1397.adoc[leveloffset=+1]
+
+
+include::modules/release-notes/snip-technology-preview-rhidp-3713.adoc[leveloffset=+1]
+
+
+
diff --git a/assemblies/assembly-rhdh-integration-aks.adoc b/assemblies/assembly-rhdh-integration-aks.adoc
new file mode 100644
index 0000000000..9f56056b9c
--- /dev/null
+++ b/assemblies/assembly-rhdh-integration-aks.adoc
@@ -0,0 +1,18 @@
+:_mod-docs-content-type: ASSEMBLY
+[id="assembly-rhdh-integration-aks"]
+= {product} integration with {aks-brand-name} ({aks-short})
+:context: assembly-rhdh-integration-aks
+
+toc::[]
+
+
+You can integrate {product-short} with {aks-brand-name} ({aks-short}), which provides a significant advancement in development, offering a streamlined environment for building, deploying, and managing your applications.
+
+This integration requires the deployment of {product-short} on {aks-short} using one of the following methods:
+
+* The Helm chart
+* The {product} Operator
+
+include::modules/admin/proc-rhdh-monitoring-logging-aks.adoc[leveloffset=+1]
+
+include::modules/admin/proc-using-azure-auth-provider.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-rhdh-integration-aws.adoc b/assemblies/assembly-rhdh-integration-aws.adoc
new file mode 100644
index 0000000000..89b2161acc
--- /dev/null
+++ b/assemblies/assembly-rhdh-integration-aws.adoc
@@ -0,0 +1,17 @@
+:_mod-docs-content-type: ASSEMBLY
+[id="assembly-rhdh-integration-aws"]
+= {product} integration with {aws-brand-name} ({aws-short})
+:context: assembly-rhdh-integration-aws
+
+toc::[]
+
+You can integrate your {product} application with {aws-brand-name} ({aws-short}), which can help you streamline your workflows within the {aws-short} ecosystem. Integrating the {product-short} resources with {aws-short} provides access to a comprehensive suite of tools, services, and solutions.
+
+The integration with {aws-short} requires the deployment of {product-short} in {eks-name} (EKS) using one of the following methods:
+
+* The Helm chart
+* The {product} Operator
+
+include::modules/admin/proc-rhdh-monitoring-logging-aws.adoc[leveloffset=+1]
+
+include::modules/admin/proc-using-aws-cognito-auth-provider.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-rhdh-observability.adoc b/assemblies/assembly-rhdh-observability.adoc
new file mode 100644
index 0000000000..a954ee8de9
--- /dev/null
+++ b/assemblies/assembly-rhdh-observability.adoc
@@ -0,0 +1,17 @@
+:_mod-docs-content-type: ASSEMBLY
+[id="assembly-rhdh-observability"]
+= Enabling observability for {product} on {ocp-short}
+:context: assembly-rhdh-observability
+
+toc::[]
+
+// Metrics
+In {ocp-short}, metrics are exposed through an HTTP service endpoint under the `/metrics` canonical name. You can create a `ServiceMonitor` custom resource (CR) to scrape metrics from a service endpoint in a user-defined project.
+
+include::modules/observability/proc-admin-enabling-metrics-ocp-helm.adoc[leveloffset=+1]
+include::modules/observability/proc-admin-enabling-metrics-ocp-operator.adoc[leveloffset=+1]
+
+[role="_additional-resources"]
+[id="additional-resources_{context}"]
+== Additional resources
+* link:https://docs.openshift.com/container-platform/latest/observability/monitoring/managing-metrics.html[{ocp-short} - Managing metrics]
diff --git a/assemblies/assembly-rhdh-telemetry.adoc b/assemblies/assembly-rhdh-telemetry.adoc
new file mode 100644
index 0000000000..435f52b0ab
--- /dev/null
+++ b/assemblies/assembly-rhdh-telemetry.adoc
@@ -0,0 +1,41 @@
+[id="assembly-rhdh-telemetry"]
+= Telemetry data collection
+
+The telemetry data collection feature helps in collecting and analyzing the telemetry data to improve your experience with {product}. This feature is enabled by default.
+
+[IMPORTANT]
+====
+As an administrator, you can disable the telemetry data collection feature based on your needs. For example, in an air-gapped environment, you can disable this feature to avoid needless outbound requests affecting the responsiveness of the {product-very-short} application. For more details, see the link:{LinkAdminGuide}#disabling-telemetry-data-collection_admin-rhdh[Disabling telemetry data collection in {product-very-short}] section.
+====
+
+{company-name} collects and analyzes the following data:
+
+* Events of page visits and clicks on links or buttons.
+* System-related information, for example, locale, timezone, user agent including browser and OS details.
+* Page-related information, for example, title, category, extension name, URL, path, referrer, and search parameters.
+* Anonymized IP addresses, recorded as `0.0.0.0`.
+* Anonymized username hashes, which are unique identifiers used solely to identify the number of unique users of the {product-very-short} application.
+
+With {product-very-short}, you can customize the telemetry data collection feature and the telemetry Segment source configuration based on your needs.
+
+
+// disabling telemetry
+include::modules/admin/ref-disabling-telemetry.adoc[leveloffset=+1]
+
+include::modules/admin/proc-disabling-telemetry-using-helm.adoc[leveloffset=+2]
+
+include::modules/admin/proc-disabling-telemetry-using-operator.adoc[leveloffset=+2]
+
+// enabling telemetry
+include::modules/admin/ref-enabling-telemetry.adoc[leveloffset=+1]
+
+include::modules/admin/proc-enabling-telemetry-using-helm.adoc[leveloffset=+2]
+
+include::modules/admin/proc-enabling-telemetry-using-operator.adoc[leveloffset=+2]
+
+// customizing telemetry segment source
+include::modules/admin/ref-customizing-telemetry-segment.adoc[leveloffset=+1]
+
+include::modules/admin/proc-customizing-telemetry-segment-using-helm.adoc[leveloffset=+2]
+
+include::modules/admin/proc-customizing-telemetry-segment-using-operator.adoc[leveloffset=+2]
diff --git a/assemblies/assembly-running-rhdh-behind-a-proxy.adoc b/assemblies/assembly-running-rhdh-behind-a-proxy.adoc
new file mode 100644
index 0000000000..d6a895a280
--- /dev/null
+++ b/assemblies/assembly-running-rhdh-behind-a-proxy.adoc
@@ -0,0 +1,13 @@
+[id="assembly-running-rhdh-behind-a-proxy"]
+= Running the {product-very-short} application behind a corporate proxy
+
+You can run the {product-very-short} application behind a corporate proxy by setting any of the following environment variables before starting the application:
+
+* `HTTP_PROXY`: Denotes the proxy to use for HTTP requests.
+* `HTTPS_PROXY`: Denotes the proxy to use for HTTPS requests.
+
+Additionally, you can set the `NO_PROXY` environment variable to exclude certain domains from proxying. The variable value is a comma-separated list of hostnames that do not require a proxy to get reached, even if one is specified.
+
+
+include::modules/admin/proc-configuring-proxy-in-helm-deployment.adoc[leveloffset=+1]
+include::modules/admin/proc-configuring-proxy-in-operator-deployment.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-techdocs-plugin.adoc b/assemblies/assembly-techdocs-plugin.adoc
new file mode 100644
index 0000000000..bf2122abdd
--- /dev/null
+++ b/assemblies/assembly-techdocs-plugin.adoc
@@ -0,0 +1,58 @@
+:_mod-docs-content-type: ASSEMBLY
+[id="assembly-techdocs-plugin_{context}"]
+= Configuring the TechDocs plugin in {product}
+
+The {product} TechDocs plugin helps your organization create, find, and use documentation in a central location and in a standardized way. For example:
+
+Docs-like-code approach::
+Write your technical documentation in Markdown files that are stored inside your project repository along with your code.
+
+Documentation site generation::
+Use MkDocs to create a full-featured, Markdown-based, static HTML site for your documentation that is rendered centrally in {product-short}.
+
+Documentation site metadata and integrations::
+See additional metadata about the documentation site alongside the static documentation, such as the date of the last update, the site owner, top contributors, open GitHub issues, Slack support channels, and Stack Overflow Enterprise tags.
+
+Built-in navigation and search::
+Find the information that you want from a document more quickly and easily.
+
+Add-ons::
+Customize your TechDocs experience with Add-ons to address higher-order documentation needs.
+
+The TechDocs plugin is preinstalled and enabled on a {product-short} instance by default. You can disable or enable the TechDocs plugin, and change other parameters, by configuring the {product} Helm chart or the {product} Operator config map.
+
+[IMPORTANT]
+====
+{product} includes a built-in TechDocs builder that generates static HTML documentation from your codebase. However, the default basic setup of the local builder is not intended for production.
+====
+
+You can use a CI/CD pipeline with the repository that has a dedicated job to generate docs for TechDocs. The generated static files are stored in {odf-name} or in a cloud storage solution of your choice and published to a static HTML documentation site.
+
+After you configure {odf-name} to store the files that TechDocs generates, you can configure the TechDocs plugin to use the {odf-name} for cloud storage.
+
+[role="_additional-resources"]
+.Additional resources
+
+* For more information, see link:{LinkPluginsGuide}[Configuring plugins in {product}].
+
+//Configuring storage
+include::modules/getting-started/con-techdocs-configure-storage.adoc[leveloffset=+1]
+
+include::modules/getting-started/proc-techdocs-using-odf-storage.adoc[leveloffset=+2]
+
+include::modules/getting-started/proc-techdocs-configure-odf-helm.adoc[leveloffset=+2]
+
+include::modules/getting-started/ref-techdocs-example-config-plugin-helm.adoc[leveloffset=+3]
+
+include::modules/getting-started/proc-techdocs-configure-odf-operator.adoc[leveloffset=+2]
+
+include::modules/getting-started/ref-techdocs-example-config-plugin-operator.adoc[leveloffset=+3]
+
+//Configuring CI/CD
+include::modules/getting-started/con-techdocs-config-cicd.adoc[leveloffset=+1]
+
+include::modules/getting-started/proc-techdocs-config-cicd-prep-repo.adoc[leveloffset=+2]
+
+include::modules/getting-started/proc-techdocs-generate-site.adoc[leveloffset=+2]
+
+include::modules/getting-started/proc-techdocs-publish-site.adoc[leveloffset=+2]
diff --git a/assemblies/assembly-upgrade-rhdh.adoc b/assemblies/assembly-upgrade-rhdh.adoc
new file mode 100644
index 0000000000..bab16c2427
--- /dev/null
+++ b/assemblies/assembly-upgrade-rhdh.adoc
@@ -0,0 +1,7 @@
+:_mod-docs-content-type: ASSEMBLY
+[id="assembly-upgrade-rhdh"]
+= Upgrading {product}
+:context: assembly-upgrade-rhdh
+
+toc::[]
+
diff --git a/assemblies/assembly_about-rhdh.adoc b/assemblies/assembly_about-rhdh.adoc
new file mode 100644
index 0000000000..17c30781f7
--- /dev/null
+++ b/assemblies/assembly_about-rhdh.adoc
@@ -0,0 +1,26 @@
+:_newdoc-version: 2.18.3
+:_template-generated: 2024-10-07
+
+ifdef::context[:parent-context-of-about-rhdh: {context}]
+
+:_mod-docs-content-type: ASSEMBLY
+
+ifndef::context[]
+[id="about-rhdh"]
+endif::[]
+ifdef::context[]
+[id="about-rhdh_{context}"]
+endif::[]
+= About {product}
+
+:context: about-rhdh
+
+{product} is a fully supported, enterprise-grade, open developer platform that you can use to build developer portals. This platform contains a supported and opinionated framework that helps reduce the friction and frustration of developers while boosting productivity. {product} simplifies decision-making by providing a developer experience that presents a selection of internally approved tools, programming languages, and developer resources within a self-managed portal. As a developer, you can use {product} to experience a streamlined development environment. {product} is driven by a centralized software catalog, providing efficiency to your microservices and infrastructure. It enables your product team to deliver quality code without any compromises.
+
+include::modules/discover/con_benefits-of-rhdh.adoc[leveloffset=+1]
+
+
+
+
+
+
diff --git a/assemblies/dynamic-plugins/assembly-about-rhdh-plugins.adoc b/assemblies/dynamic-plugins/assembly-about-rhdh-plugins.adoc
new file mode 100644
index 0000000000..b518961b23
--- /dev/null
+++ b/assemblies/dynamic-plugins/assembly-about-rhdh-plugins.adoc
@@ -0,0 +1,4 @@
+[id="rhdh-about-rhdh-plugins_{context}"]
+= About {product} plugins
+
+include::../modules/dynamic-plugins/con-rhdh-plugins.adoc[leveloffset=+1]
\ No newline at end of file
diff --git a/assemblies/dynamic-plugins/assembly-configuring-rhdh-plugins.adoc b/assemblies/dynamic-plugins/assembly-configuring-rhdh-plugins.adoc
new file mode 100644
index 0000000000..c151708b37
--- /dev/null
+++ b/assemblies/dynamic-plugins/assembly-configuring-rhdh-plugins.adoc
@@ -0,0 +1,28 @@
+[id="rhdh-configuring-rhdh-plugins_{context}"]
+= Configuring dynamic plugins in {product}
+
+// Ansible
+include::../modules/dynamic-plugins/con-ansible-plugin-admin.adoc[leveloffset=+1]
+
+// Argo CD
+include::../../artifacts/rhdh-plugins-reference/argocd/argocd-plugin-admin.adoc[leveloffset=+1]
+
+// Keycloak
+include::../../artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-admin.adoc[leveloffset=+1]
+
+// Nexus
+include::../../artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-admin.adoc[leveloffset=+1]
+
+// Tekton
+include::../../artifacts/rhdh-plugins-reference/tekton/tekton-plugin-admin.adoc[leveloffset=+1]
+
+// Topology
+== Installing and configuring the Topology plugin
+include::../modules/dynamic-plugins/proc-topology-install.adoc[leveloffset=+2]
+include::../modules/dynamic-plugins/proc-topology-configure.adoc[leveloffset=+2]
+
+// Dynamic plugins cache
+include::../modules/dynamic-plugins/con-dynamic-plugins-cache.adoc[ leveloffset=+1]
+
+// Redis cache
+include::../modules/dynamic-plugins/proc-installing-and-configuring-redis-cache.adoc[leveloffset=+1]
\ No newline at end of file
diff --git a/assemblies/dynamic-plugins/assembly-installing-rhdh-plugins.adoc b/assemblies/dynamic-plugins/assembly-installing-rhdh-plugins.adoc
new file mode 100644
index 0000000000..70b58f271b
--- /dev/null
+++ b/assemblies/dynamic-plugins/assembly-installing-rhdh-plugins.adoc
@@ -0,0 +1,25 @@
+[id="rhdh-installing-rhdh-plugins_{context}"]
+= Installing dynamic plugins in {product}
+
+The dynamic plugin support is based on the backend plugin manager package, which is a service that scans a configured root directory (`dynamicPlugins.rootDirectory` in the `app-config.yaml` file) for dynamic plugin packages and loads them dynamically.
+
+You can use the dynamic plugins that come preinstalled with {product} or install external dynamic plugins from a public NPM registry.
+
+// Operator installation
+include::../modules/dynamic-plugins/proc-config-dynamic-plugins-rhdh-operator.adoc[leveloffset=+1]
+
+// Helm installation
+include::../modules/dynamic-plugins/con-install-dynamic-plugin-helm.adoc[leveloffset=+1]
+include::../modules/dynamic-plugins/proc-obtaining-integrity-checksum.adoc[leveloffset=+2]
+include::../modules/dynamic-plugins/ref-example-dynamic-plugin-helm-installations.adoc[leveloffset=+2]
+include::../modules/dynamic-plugins/proc-rhdh-example-external-dynamic-plugins.adoc[leveloffset=+2]
+
+// Air gapped environment
+//include::../modules/dynamic-plugins/proc-rhdh-installing-external-dynamic-plugins-airgapped.adoc[leveloffset=+1]
+include::../modules/dynamic-plugins/proc-using-custom-npm-registry.adoc[leveloffset=+1]
+
+// Viewing installed plugins
+include::../modules/dynamic-plugins/proc-viewing-installed-plugins.adoc[leveloffset=+1]
+
+//basic plugin configuration
+//include::../modules/dynamic-plugins/con-basic-config-dynamic-plugins.adoc[leveloffset=+1]
\ No newline at end of file
diff --git a/assemblies/dynamic-plugins/assembly-reference-rhdh-plugins.adoc b/assemblies/dynamic-plugins/assembly-reference-rhdh-plugins.adoc
new file mode 100644
index 0000000000..a54d577027
--- /dev/null
+++ b/assemblies/dynamic-plugins/assembly-reference-rhdh-plugins.adoc
@@ -0,0 +1,11 @@
+[id="rhdh-reference-rhdh-plugins_{context}"]
+= Plugins reference
+
+include::../modules/dynamic-plugins/con-preinstalled-dynamic-plugins.adoc[leveloffset=+1]
+
+include::../modules/dynamic-plugins/proc-viewing-installed-plugins.adoc[leveloffset=+1]
+
+[id="rhdh-supported-plugins"]
+include::../modules/dynamic-plugins/ref-rh-supported-plugins.adoc[leveloffset=+1]
+include::../modules/dynamic-plugins/ref-rh-tech-preview-plugins.adoc[leveloffset=+1]
+include::../modules/dynamic-plugins/ref-community-plugins.adoc[leveloffset=+1]
\ No newline at end of file
diff --git a/assemblies/dynamic-plugins/assembly-rhdh-installing-dynamic-plugins.adoc b/assemblies/dynamic-plugins/assembly-rhdh-installing-dynamic-plugins.adoc
new file mode 100644
index 0000000000..47b7c26d9c
--- /dev/null
+++ b/assemblies/dynamic-plugins/assembly-rhdh-installing-dynamic-plugins.adoc
@@ -0,0 +1,41 @@
+[id="rhdh-installing-dynamic-plugins"]
+= Dynamic plugin installation
+
+The dynamic plugin support is based on the backend plugin manager package, which is a service that scans a configured root directory (`dynamicPlugins.rootDirectory` in the app config) for dynamic plugin packages and loads them dynamically.
+
+You can use the dynamic plugins that come preinstalled with {product} or install external dynamic plugins from a public NPM registry.
+
+// Preinstalled plugins
+include::../modules/dynamic-plugins/con-preinstalled-dynamic-plugins.adoc[leveloffset=+1]
+
+// Dynamic plugins tables
+
+// Red Hat Generally Available supported plugins
+include::../modules/dynamic-plugins/ref-rh-supported-plugins.adoc[leveloffset=+3]
+
+[NOTE]
+====
+* For more information about configuring KeyCloak, see link:{plugins-configure-book-url}[{plugins-configure-book-title}].
+
+* For more information about configuring TechDocs, see link:{LinkAdminGuide}#assembly-techdocs-plugin_{context}[Configuring the TechDocs plugin in {product}].
+====
+
+// Technology preview support statement
+include::../../artifacts/snip-dynamic-plugins-support.adoc[leveloffset=+3]
+
+// Red Hat Technology Preview plugins
+[id="rhdh-tech-preview-plugins"]
+include::../modules/dynamic-plugins/ref-rh-tech-preview-plugins.adoc[leveloffset=+4]
+
+[NOTE]
+====
+* A new Technology Preview plugin for Red Hat Ansible Automation Platform (RHAAP) is available, which replaces this older one. See link:{LinkPluginsGuide}#rhdh-compatible-plugins[Other installable plugins] in the _{NameOfPluginsGuide} guide_ for further details. See xref:rhdh-compatible-plugins[Dynamic plugins support matrix].
+====
+
+// Community plugins
+[id="rhdh-community-plugins"]
+include::../modules/dynamic-plugins/ref-community-plugins.adoc[leveloffset=+4]
+
+// Red Hat compatible plugins
+[id="rhdh-compatible-plugins"]
+include::../modules/dynamic-plugins/ref-rh-compatible-plugins.adoc[leveloffset=+1]
\ No newline at end of file
diff --git a/assemblies/dynamic-plugins/assembly-troubleshooting-rhdh-plugins.adoc b/assemblies/dynamic-plugins/assembly-troubleshooting-rhdh-plugins.adoc
new file mode 100644
index 0000000000..566325a98a
--- /dev/null
+++ b/assemblies/dynamic-plugins/assembly-troubleshooting-rhdh-plugins.adoc
@@ -0,0 +1,4 @@
+[id="rhdh-troubleshooting-rhdh-plugins_{context}"]
+= Troubleshooting {product-short} plugins
+
+//include::../modules/dynamic-plugins/con-rhdh-plugins.adoc[leveloffset=+1]
\ No newline at end of file
diff --git a/assemblies/dynamic-plugins/assembly-using-rhdh-plugins.adoc b/assemblies/dynamic-plugins/assembly-using-rhdh-plugins.adoc
new file mode 100644
index 0000000000..12560a1799
--- /dev/null
+++ b/assemblies/dynamic-plugins/assembly-using-rhdh-plugins.adoc
@@ -0,0 +1,20 @@
+[id="rhdh-using-rhdh-plugins_{context}"]
+= Using dynamic plugins
+
+// Ansible
+include::../modules/dynamic-plugins/con-ansible-plugin-user.adoc[leveloffset=+1]
+
+// Argo CD
+include::../../artifacts/rhdh-plugins-reference/argocd/argocd-plugin-user.adoc[leveloffset=+1]
+
+// Keycloak
+include::../../artifacts/rhdh-plugins-reference/keycloak/keycloak-plugin-user.adoc[leveloffset=+1]
+
+// Nexus
+include::../../artifacts/rhdh-plugins-reference/nexus-repository-manager/nexus-repository-manager-plugin-user.adoc[leveloffset=+1]
+
+// Tekton
+include::../../artifacts/rhdh-plugins-reference/tekton/tekton-plugin-user.adoc[leveloffset=+1]
+
+// Topology
+include::../../modules/dynamic-plugins/proc-using-topology-plugin.adoc[leveloffset=+1]
\ No newline at end of file
diff --git a/assemblies/images b/assemblies/images
new file mode 120000
index 0000000000..5fa6987088
--- /dev/null
+++ b/assemblies/images
@@ -0,0 +1 @@
+../../images
\ No newline at end of file
diff --git a/assemblies/modules b/assemblies/modules
new file mode 120000
index 0000000000..464b823aca
--- /dev/null
+++ b/assemblies/modules
@@ -0,0 +1 @@
+../modules
\ No newline at end of file
diff --git a/build/scripts/build-ccutil.sh b/build/scripts/build-ccutil.sh
new file mode 100755
index 0000000000..67ef5737ed
--- /dev/null
+++ b/build/scripts/build-ccutil.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# Copyright (c) 2025 Red Hat, Inc.
+# This program and the accompanying materials are made
+# available under the terms of the Eclipse Public License 2.0
+# which is available at https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Utility script build html previews with referenced images
+# Requires: Podman - see https://podman.io
+# input: titles/
+# output: titles-generated/ and titles-generated/$BRANCH/
+
+# grep regex for title folders to exclude from processing below
+EXCLUDED_TITLES="rhdh-plugins-reference"
+BRANCH="main"
+
+while [[ "$#" -gt 0 ]]; do
+ case $1 in
+ '-b') BRANCH="$2"; shift 1;;
+ esac
+ shift 1
+done
+
+rm -fr titles-generated/;
+mkdir -p titles-generated/"${BRANCH}";
+echo "Red Hat Developer Hub Documentation Preview - ${BRANCH}
" > titles-generated/"${BRANCH}"/index.html;
+# exclude the rhdh-plugins-reference as it's embedded in the admin guide
+# shellcheck disable=SC2044,SC2013
+set -e
+for t in $(find titles -name master.adoc | sort -uV | grep -E -v "${EXCLUDED_TITLES}"); do
+ d=${t%/*};
+ dest=${d/titles/titles-generated\/${BRANCH}};
+ rm -rf "$d/build" || true
+ CMD="podman run --interactive --rm --tty \
+ --volume "$(pwd)":/docs:Z \
+ --workdir "/docs/$d" \
+ quay.io/ivanhorvath/ccutil:amazing ccutil compile --format html-single --lang en-US";
+ echo -e -n "\nBuilding $t into $dest ...\n ";
+ echo "${CMD}" | sed -r -e "s/\ +/ \\\\\n /g"
+ $CMD
+ rm -rfv "$dest" || true
+ mv -f "$d/build/tmp/en-US/html-single/" "$dest"
+ # shellcheck disable=SC2013
+ for im in $(grep images/ "$dest/index.html" | grep -E -v 'mask-image|background|fa-icons|jupumbra' | sed -r -e "s#.+(images/[^\"]+)\".+#\1#"); do
+ # echo " Copy $im ...";
+ IMDIR="$dest/${im%/*}/"
+ mkdir -p "${IMDIR}"; rsync -q "$im" "${IMDIR}";
+ done
+ # shellcheck disable=SC2044
+ # for f in $(find "$dest/" -type f); do echo " $f"; done
+ echo "
" >> titles-generated/pulls.html
+ fi
+else
+ # fetch the existing https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/index.html to add prs and branches
+ curl -sSL https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/index.html -o titles-generated/index.html
+ if [[ -z $(grep "./${BRANCH}/index.html" titles-generated/index.html) ]]; then
+ echo "Building root index for $BRANCH in titles-generated/index.html ...";
+ echo "
" >> titles-generated/index.html
+ fi
+fi
diff --git a/build/scripts/build.sh b/build/scripts/build.sh
new file mode 100755
index 0000000000..7d9b149d86
--- /dev/null
+++ b/build/scripts/build.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+#
+# Copyright (c) 2023-2024 Red Hat, Inc.
+# This program and the accompanying materials are made
+# available under the terms of the Eclipse Public License 2.0
+# which is available at https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Utility script build html previews with referenced images
+# Requires: asciidoctor - see https://docs.asciidoctor.org/asciidoctor/latest/install/linux-packaging/
+# input: titles/
+# output: titles-generated/ and titles-generated/$BRANCH/
+
+# grep regex for title folders to exclude from processing below
+EXCLUDED_TITLES="rhdh-plugins-reference"
+BRANCH="main"
+
+while [[ "$#" -gt 0 ]]; do
+ case $1 in
+ '-b') BRANCH="$2"; shift 1;;
+ esac
+ shift 1
+done
+
+rm -fr titles-generated/;
+mkdir -p titles-generated/"${BRANCH}";
+echo "Red Hat Developer Hub Documentation Preview - ${BRANCH}
" > titles-generated/"${BRANCH}"/index.html;
+# exclude the rhdh-plugins-reference as it's embedded in the admin guide
+# shellcheck disable=SC2044,SC2013
+set -e
+for t in $(find titles -name master.adoc | sort -uV | grep -E -v "${EXCLUDED_TITLES}"); do
+ d=${t%/*}; d=${d/titles/titles-generated\/${BRANCH}};
+ CMD="asciidoctor \
+ --backend=html5 \
+ --destination-dir $d \
+ --failure-level ERROR \
+ --section-numbers \
+ --trace \
+ --warnings \
+ -a chapter-signifier=Chapter \
+ -a sectnumslevels=5 \
+ -a source-highlighter=coderay \
+ -a stylesdir=$(pwd)/.asciidoctor \
+ -a stylesheet=docs.css \
+ -a toc=left \
+ -a toclevels=5 \
+ -o index.html \
+ $t";
+ echo -e -n "\nBuilding $t into $d ...\n ";
+ echo "${CMD}" | sed -r -e "s/\ +/ \\\\\n /g"
+ $CMD
+ # shellcheck disable=SC2013
+ for im in $(grep images/ "$d/index.html" | grep -E -v 'mask-image|background|fa-icons|jupumbra' | sed -r -e "s#.+(images/[^\"]+)\".+#\1#"); do
+ # echo " Copy $im ...";
+ IMDIR="$d/${im%/*}/"
+ mkdir -p "${IMDIR}"; rsync -q "$im" "${IMDIR}";
+ done
+ # shellcheck disable=SC2044
+ for f in $(find "$d/" -type f); do echo " $f"; done
+ echo "
" >> titles-generated/pulls.html
+ fi
+else
+ # fetch the existing https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/index.html to add prs and branches
+ curl -sSL https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/index.html -o titles-generated/index.html
+ if [[ -z $(grep "./${BRANCH}/index.html" titles-generated/index.html) ]]; then
+ echo "Building root index for $BRANCH in titles-generated/index.html ...";
+ echo "
" >> titles-generated/index.html
+ fi
+fi
diff --git a/build/templates/assembly.adoc.jinja b/build/templates/assembly.adoc.jinja
new file mode 100644
index 0000000000..ec4de48353
--- /dev/null
+++ b/build/templates/assembly.adoc.jinja
@@ -0,0 +1,12 @@
+:_content-type: ASSEMBLY
+[id="{{ assembly_id }}"]
+= {{ assembly_title }}
+
+{{ assembly_introduction | default(omit) }}
+{% for issue in vars %}
+include::modules/release-notes/snip-{{ issue.fields.customfield_12320850 | lower | replace(" ", "-") }}-{{ issue.key | lower }}.adoc[leveloffset=+1]
+
+{% endfor %}
+{% if not vars %}
+None.
+{% endif %}
diff --git a/build/templates/snippet-security.adoc.jinja2 b/build/templates/snippet-security.adoc.jinja2
new file mode 100644
index 0000000000..782002e6fd
--- /dev/null
+++ b/build/templates/snippet-security.adoc.jinja2
@@ -0,0 +1 @@
+{{ text }}
diff --git a/build/templates/snippet-with-jira-link.adoc.jinja2 b/build/templates/snippet-with-jira-link.adoc.jinja2
new file mode 100644
index 0000000000..27b1c7f65c
--- /dev/null
+++ b/build/templates/snippet-with-jira-link.adoc.jinja2
@@ -0,0 +1,7 @@
+[id="{{ id }}"]
+= {{ title }}
+
+{{ text }}
+
+.Additional resources
+* link:https://issues.redhat.com/browse/{{ key }}[{{ key }}]
diff --git a/build/templates/snippet-without-jira-link.adoc.jinja2 b/build/templates/snippet-without-jira-link.adoc.jinja2
new file mode 100644
index 0000000000..0b45157dad
--- /dev/null
+++ b/build/templates/snippet-without-jira-link.adoc.jinja2
@@ -0,0 +1,7 @@
+[id="{{ id }}"]
+= {{ title }}
+
+{{ text }}
+
+// .Additional resources
+// * link:https://issues.redhat.com/browse/{{ key }}[{{ key }}]
diff --git a/images/rhdh-plugins-reference/aap-backend-plugin-user1.png b/images/rhdh-plugins-reference/aap-backend-plugin-user1.png
new file mode 100644
index 0000000000..d55458b1e8
Binary files /dev/null and b/images/rhdh-plugins-reference/aap-backend-plugin-user1.png differ
diff --git a/images/rhdh-plugins-reference/aap-backend-plugin-user2.png b/images/rhdh-plugins-reference/aap-backend-plugin-user2.png
new file mode 100644
index 0000000000..fc081e49c4
Binary files /dev/null and b/images/rhdh-plugins-reference/aap-backend-plugin-user2.png differ
diff --git a/images/rhdh-plugins-reference/acr-plugin-user1.png b/images/rhdh-plugins-reference/acr-plugin-user1.png
new file mode 100644
index 0000000000..5252732ecb
Binary files /dev/null and b/images/rhdh-plugins-reference/acr-plugin-user1.png differ
diff --git a/images/rhdh-plugins-reference/argo-cd-plugin-history.png b/images/rhdh-plugins-reference/argo-cd-plugin-history.png
new file mode 100644
index 0000000000..21374a4667
Binary files /dev/null and b/images/rhdh-plugins-reference/argo-cd-plugin-history.png differ
diff --git a/images/rhdh-plugins-reference/argo-cd-plugin-overview-card-details.png b/images/rhdh-plugins-reference/argo-cd-plugin-overview-card-details.png
new file mode 100644
index 0000000000..8c5cf048bb
Binary files /dev/null and b/images/rhdh-plugins-reference/argo-cd-plugin-overview-card-details.png differ
diff --git a/images/rhdh-plugins-reference/argo-cd-plugin-overview-card.png b/images/rhdh-plugins-reference/argo-cd-plugin-overview-card.png
new file mode 100644
index 0000000000..ea18dd1004
Binary files /dev/null and b/images/rhdh-plugins-reference/argo-cd-plugin-overview-card.png differ
diff --git a/images/rhdh-plugins-reference/argocd.png b/images/rhdh-plugins-reference/argocd.png
new file mode 100644
index 0000000000..d8efd01aca
Binary files /dev/null and b/images/rhdh-plugins-reference/argocd.png differ
diff --git a/images/rhdh-plugins-reference/deployment_summary.png b/images/rhdh-plugins-reference/deployment_summary.png
new file mode 100644
index 0000000000..a24b5cc882
Binary files /dev/null and b/images/rhdh-plugins-reference/deployment_summary.png differ
diff --git a/images/rhdh-plugins-reference/group1.jpg b/images/rhdh-plugins-reference/group1.jpg
new file mode 100644
index 0000000000..4b9a277ac4
Binary files /dev/null and b/images/rhdh-plugins-reference/group1.jpg differ
diff --git a/images/rhdh-plugins-reference/jfrog-plugin-user1.png b/images/rhdh-plugins-reference/jfrog-plugin-user1.png
new file mode 100644
index 0000000000..ff04ff1e4e
Binary files /dev/null and b/images/rhdh-plugins-reference/jfrog-plugin-user1.png differ
diff --git a/images/rhdh-plugins-reference/link.png b/images/rhdh-plugins-reference/link.png
new file mode 100644
index 0000000000..bf5e4887af
Binary files /dev/null and b/images/rhdh-plugins-reference/link.png differ
diff --git a/images/rhdh-plugins-reference/nexus-repository-manager.png b/images/rhdh-plugins-reference/nexus-repository-manager.png
new file mode 100644
index 0000000000..fdb63a1de0
Binary files /dev/null and b/images/rhdh-plugins-reference/nexus-repository-manager.png differ
diff --git a/images/rhdh-plugins-reference/ocm-plugin-user1.png b/images/rhdh-plugins-reference/ocm-plugin-user1.png
new file mode 100644
index 0000000000..3550b5463f
Binary files /dev/null and b/images/rhdh-plugins-reference/ocm-plugin-user1.png differ
diff --git a/images/rhdh-plugins-reference/ocm-plugin-user2.png b/images/rhdh-plugins-reference/ocm-plugin-user2.png
new file mode 100644
index 0000000000..49c6211334
Binary files /dev/null and b/images/rhdh-plugins-reference/ocm-plugin-user2.png differ
diff --git a/images/rhdh-plugins-reference/quay-plugin-backstage1.png b/images/rhdh-plugins-reference/quay-plugin-backstage1.png
new file mode 100644
index 0000000000..0b732eab34
Binary files /dev/null and b/images/rhdh-plugins-reference/quay-plugin-backstage1.png differ
diff --git a/images/rhdh-plugins-reference/quay-plugin-backstage2.png b/images/rhdh-plugins-reference/quay-plugin-backstage2.png
new file mode 100644
index 0000000000..9ea03e373b
Binary files /dev/null and b/images/rhdh-plugins-reference/quay-plugin-backstage2.png differ
diff --git a/images/rhdh-plugins-reference/quay-plugin-backstage3.png b/images/rhdh-plugins-reference/quay-plugin-backstage3.png
new file mode 100644
index 0000000000..02aa179e57
Binary files /dev/null and b/images/rhdh-plugins-reference/quay-plugin-backstage3.png differ
diff --git a/images/rhdh-plugins-reference/sidebar.png b/images/rhdh-plugins-reference/sidebar.png
new file mode 100644
index 0000000000..5a61b95864
Binary files /dev/null and b/images/rhdh-plugins-reference/sidebar.png differ
diff --git a/images/rhdh-plugins-reference/tekton-plugin-pipeline-expand.png b/images/rhdh-plugins-reference/tekton-plugin-pipeline-expand.png
new file mode 100644
index 0000000000..b4b7872ac3
Binary files /dev/null and b/images/rhdh-plugins-reference/tekton-plugin-pipeline-expand.png differ
diff --git a/images/rhdh-plugins-reference/tekton-plugin-pipeline.png b/images/rhdh-plugins-reference/tekton-plugin-pipeline.png
new file mode 100644
index 0000000000..c6296a1305
Binary files /dev/null and b/images/rhdh-plugins-reference/tekton-plugin-pipeline.png differ
diff --git a/images/rhdh-plugins-reference/tekton-plugin-user1.png b/images/rhdh-plugins-reference/tekton-plugin-user1.png
new file mode 100644
index 0000000000..c45dcade4c
Binary files /dev/null and b/images/rhdh-plugins-reference/tekton-plugin-user1.png differ
diff --git a/images/rhdh-plugins-reference/tekton-plugin-user2.png b/images/rhdh-plugins-reference/tekton-plugin-user2.png
new file mode 100644
index 0000000000..38ff4cd33e
Binary files /dev/null and b/images/rhdh-plugins-reference/tekton-plugin-user2.png differ
diff --git a/images/rhdh-plugins-reference/tekton-plugin-user3.png b/images/rhdh-plugins-reference/tekton-plugin-user3.png
new file mode 100644
index 0000000000..cbe6aabde6
Binary files /dev/null and b/images/rhdh-plugins-reference/tekton-plugin-user3.png differ
diff --git a/images/rhdh-plugins-reference/topology-tab-user1.png b/images/rhdh-plugins-reference/topology-tab-user1.png
new file mode 100644
index 0000000000..4d8338ce35
Binary files /dev/null and b/images/rhdh-plugins-reference/topology-tab-user1.png differ
diff --git a/images/rhdh-plugins-reference/topology-tab-user2.png b/images/rhdh-plugins-reference/topology-tab-user2.png
new file mode 100644
index 0000000000..e01fd70953
Binary files /dev/null and b/images/rhdh-plugins-reference/topology-tab-user2.png differ
diff --git a/images/rhdh-plugins-reference/topology-tab-user3.png b/images/rhdh-plugins-reference/topology-tab-user3.png
new file mode 100644
index 0000000000..23862ec211
Binary files /dev/null and b/images/rhdh-plugins-reference/topology-tab-user3.png differ
diff --git a/images/rhdh-plugins-reference/user-list.jpg b/images/rhdh-plugins-reference/user-list.jpg
new file mode 100644
index 0000000000..344fd51353
Binary files /dev/null and b/images/rhdh-plugins-reference/user-list.jpg differ
diff --git a/images/rhdh-plugins-reference/user2.jpg b/images/rhdh-plugins-reference/user2.jpg
new file mode 100644
index 0000000000..95d29b7666
Binary files /dev/null and b/images/rhdh-plugins-reference/user2.jpg differ
diff --git a/images/rhdh-plugins-reference/users.jpg b/images/rhdh-plugins-reference/users.jpg
new file mode 100644
index 0000000000..393f14bdd5
Binary files /dev/null and b/images/rhdh-plugins-reference/users.jpg differ
diff --git a/images/rhdh/disabling-telemetry.png b/images/rhdh/disabling-telemetry.png
new file mode 100644
index 0000000000..ead66f664b
Binary files /dev/null and b/images/rhdh/disabling-telemetry.png differ
diff --git a/images/rhdh/enable-gh-discovery.png b/images/rhdh/enable-gh-discovery.png
new file mode 100644
index 0000000000..0b76eb16f6
Binary files /dev/null and b/images/rhdh/enable-gh-discovery.png differ
diff --git a/images/rhdh/enable-gh-member-discovery.png b/images/rhdh/enable-gh-member-discovery.png
new file mode 100644
index 0000000000..9a2897ca03
Binary files /dev/null and b/images/rhdh/enable-gh-member-discovery.png differ
diff --git a/images/rhdh/example-callback-url.png b/images/rhdh/example-callback-url.png
new file mode 100644
index 0000000000..1a8ce804b5
Binary files /dev/null and b/images/rhdh/example-callback-url.png differ
diff --git a/images/rhdh/helm-upgrade.png b/images/rhdh/helm-upgrade.png
new file mode 100644
index 0000000000..c2568814ee
Binary files /dev/null and b/images/rhdh/helm-upgrade.png differ
diff --git a/images/rhdh/operator-install-1.png b/images/rhdh/operator-install-1.png
new file mode 100644
index 0000000000..d2d4a34425
Binary files /dev/null and b/images/rhdh/operator-install-1.png differ
diff --git a/images/rhdh/operator-install-2.png b/images/rhdh/operator-install-2.png
new file mode 100644
index 0000000000..479ac57d52
Binary files /dev/null and b/images/rhdh/operator-install-2.png differ
diff --git a/images/rhdh/rhdh-helm-install.png b/images/rhdh/rhdh-helm-install.png
new file mode 100644
index 0000000000..b7a1958055
Binary files /dev/null and b/images/rhdh/rhdh-helm-install.png differ
diff --git a/images/rhdh/segment-source-helm.png b/images/rhdh/segment-source-helm.png
new file mode 100644
index 0000000000..0b903b7eab
Binary files /dev/null and b/images/rhdh/segment-source-helm.png differ
diff --git a/images/rhdh/template-editor.png b/images/rhdh/template-editor.png
new file mode 100644
index 0000000000..43b7497cf9
Binary files /dev/null and b/images/rhdh/template-editor.png differ
diff --git a/images/rhdh/upgrade-helm-metrics.png b/images/rhdh/upgrade-helm-metrics.png
new file mode 100644
index 0000000000..2bffa0c7f6
Binary files /dev/null and b/images/rhdh/upgrade-helm-metrics.png differ
diff --git a/images/user-guide/custom-theme-mode-1.png b/images/user-guide/custom-theme-mode-1.png
new file mode 100644
index 0000000000..377a15c9bb
Binary files /dev/null and b/images/user-guide/custom-theme-mode-1.png differ
diff --git a/jira2asciidoc.yml b/jira2asciidoc.yml
new file mode 100644
index 0000000000..b99a7c824c
--- /dev/null
+++ b/jira2asciidoc.yml
@@ -0,0 +1,94 @@
+---
+jira:
+ server: 'https://issues.redhat.com'
+product:
+ version:
+ minor_glob: 1.3.*
+ patch: 1.3
+sections:
+ - id: new-features
+ title: New features
+ description: |
+ This section highlights new features in {product} {product-version}.
+ query: >
+ project = "Red Hat Internal Developer Platform"
+ AND "Release Note Status" = "Done"
+ AND level is EMPTY
+ AND status in (Closed, "Release Pending")
+ AND "Release Note Type" in ("Feature", "Enhancement")
+ AND (fixVersion ~ "{version_minor_glob}" OR fixVersion = "{version_patch}")
+ ORDER BY key
+ template: without-jira-link
+ - id: breaking-changes
+ title: Breaking changes
+ description: |
+ This section lists breaking changes in {product} {product-version}.
+ query: >
+ project = "Red Hat Internal Developer Platform"
+ AND "Release Note Status" = "Done"
+ AND level is EMPTY
+ AND status in (Closed, "Release Pending")
+ AND "Release Note Type" in ("Removed Functionality")
+ AND (fixVersion ~ "{version_minor_glob}" OR fixVersion = "{version_patch}")
+ ORDER BY key
+ template: with-jira-link
+ - id: deprecated-functionalities
+ title: Deprecated functionalities
+ description: |
+ This section lists deprecated functionalities in {product} {product-version}.
+ query: >
+ project = "Red Hat Internal Developer Platform"
+ AND "Release Note Status" = "Done"
+ AND level is EMPTY
+ AND status in (Closed, "Release Pending")
+ AND "Release Note Type" in ("Deprecated Functionality")
+ AND (fixVersion ~ "{version_minor_glob}" OR fixVersion = "{version_patch}")
+ ORDER BY key
+ template: with-jira-link
+ - id: technology-preview
+ title: Technology Preview
+ description: |
+ This section lists Technology Preview features in {product} {product-version}.
+
+ [IMPORTANT]
+ ====
+ Technology Preview features provide early access to upcoming product innovations, enabling you to test functionality and provide feedback during the development process.
+ However, these features are not fully supported under Red Hat Subscription Level Agreements, may not be functionally complete, and are not intended for production use.
+ As Red Hat considers making future iterations of Technology Preview features generally available, we will attempt to resolve any issues that customers experience when using these features.
+ See: link:https://access.redhat.com/support/offerings/techpreview/[Technology Preview support scope].
+ ====
+ query: >
+ project = "Red Hat Internal Developer Platform"
+ AND "Release Note Status" = "Done"
+ AND level is EMPTY
+ AND status in (Closed, "Release Pending")
+ AND "Release Note Type" in ("Developer Preview", "Technology Preview")
+ AND (fixVersion ~ "{version_minor_glob}" OR fixVersion = "{version_patch}")
+ ORDER BY key
+ template: with-jira-link
+ - id: fixed-issues
+ title: Fixed issues
+ description: |
+ This section lists issues fixed in {product} {product-version}.
+ query: >
+ project = "Red Hat Internal Developer Platform"
+ AND "Release Note Status" = "Done"
+ AND level is EMPTY
+ AND status in (Closed, "Release Pending")
+ AND "Release Note Type" = "Bug Fix"
+ AND (fixVersion ~ "{version_minor_glob}" OR fixVersion = "{version_patch}")
+ ORDER BY key
+ template: with-jira-link
+ - id: known-issues
+ title: Known issues
+ description: |
+ This section lists known issues in {product} {product-version}.
+ query: >
+ project = "Red Hat Internal Developer Platform"
+ AND "Release Note Status" = "Done"
+ AND level is EMPTY
+ AND "Release Note Type" in ("Known Issue")
+ AND affectedVersion <= "{version_patch}"
+ AND (fixVersion > "{version_patch}" OR fixVersion is EMPTY)
+ ORDER BY key DESC
+ template: with-jira-link
diff --git a/modules/admin/proc-configuring-postgresql-instance-using-helm.adoc b/modules/admin/proc-configuring-postgresql-instance-using-helm.adoc
new file mode 100644
index 0000000000..f45bfec0ee
--- /dev/null
+++ b/modules/admin/proc-configuring-postgresql-instance-using-helm.adoc
@@ -0,0 +1,162 @@
+[id="proc-configuring-postgresql-instance-using-helm_{context}"]
+= Configuring an external PostgreSQL instance using the Helm Chart
+
+You can configure an external PostgreSQL instance by using the Helm Chart. By default, the Helm Chart creates and manages a local instance of PostgreSQL in the same namespace where you have deployed the {product-very-short} instance. However, you can change this default setting to configure an external PostgreSQL database server, for example, Amazon Web Services (AWS) Relational Database Service (RDS) or Azure database.
+
+.Prerequisites
+
+* You are using a supported version of PostgreSQL. For more information, see the link:https://access.redhat.com/support/policy/updates/developerhub[Product life cycle page].
+* You have the following details:
+** `db-host`: Denotes your PostgreSQL instance Domain Name System (DNS) or IP address
+** `db-port`: Denotes your PostgreSQL instance port number, such as `5432`
+** `username`: Denotes the user name to connect to your PostgreSQL instance
+** `password`: Denotes the password to connect to your PostgreSQL instance
+* You have installed the {product-very-short} application by using the Helm Chart.
+* Optional: You have a CA certificate, Transport Layer Security (TLS) private key, and TLS certificate so that you can secure your database connection by using the TLS protocol. For more information, refer to your PostgreSQL vendor documentation.
+
+[NOTE]
+====
+By default, {product-short} uses a database for each plugin and automatically creates it if none is found. You might need the `Create Database` privilege in addition to `PSQL Database` privileges for configuring an external PostgreSQL instance.
+====
+
+
+.Procedure
+
+. Optional: Create a certificate secret to configure your PostgreSQL instance with a TLS connection:
++
+[source,terminal]
+----
+cat < create -f -
+apiVersion: v1
+kind: Secret
+metadata:
+ name: <1>
+type: Opaque
+stringData:
+ postgres-ca.pem: |-
+ -----BEGIN CERTIFICATE-----
+ <2>
+ postgres-key.key: |-
+ -----BEGIN CERTIFICATE-----
+ <3>
+ postgres-crt.pem: |-
+ -----BEGIN CERTIFICATE-----
+ <4>
+ # ...
+EOF
+----
+<1> Provide the name of the certificate secret.
+<2> Provide the CA certificate key.
+<3> Optional: Provide the TLS private key.
+<4> Optional: Provide the TLS certificate key.
+
+. Create a credential secret to connect with the PostgreSQL instance:
++
+[source,terminal]
+----
+cat < create -f -
+apiVersion: v1
+kind: Secret
+metadata:
+ name: <1>
+type: Opaque
+stringData: <2>
+ POSTGRES_PASSWORD:
+ POSTGRES_PORT: ""
+ POSTGRES_USER:
+ POSTGRES_HOST:
+ PGSSLMODE: # for TLS connection <3>
+ NODE_EXTRA_CA_CERTS: # for TLS connection, e.g. /opt/app-root/src/postgres-crt.pem <4>
+EOF
+----
+<1> Provide the name of the credential secret.
+<2> Provide credential data to connect with your PostgreSQL instance.
+<3> Optional: Provide the value based on the required link:https://www.postgresql.org/docs/15/libpq-connect.html#LIBPQ-CONNECT-SSLMODE[Secure Sockets Layer (SSL) mode].
+<4> Optional: Provide the value only if you need a TLS connection for your PostgreSQL instance.
+
+. Configure your PostgreSQL instance in the Helm configuration file named `values.yaml`:
++
+[source,yaml]
+----
+# ...
+upstream:
+ postgresql:
+ enabled: false # disable PostgreSQL instance creation <1>
+ auth:
+ existingSecret: # inject credentials secret to Backstage <2>
+ backstage:
+ appConfig:
+ backend:
+ database:
+ connection: # configure Backstage DB connection parameters
+ host: ${POSTGRES_HOST}
+ port: ${POSTGRES_PORT}
+ user: ${POSTGRES_USER}
+ password: ${POSTGRES_PASSWORD}
+ ssl:
+ rejectUnauthorized: true,
+ ca:
+ $file: /opt/app-root/src/postgres-ca.pem
+ key:
+ $file: /opt/app-root/src/postgres-key.key
+ cert:
+ $file: /opt/app-root/src/postgres-crt.pem
+ extraEnvVarsSecrets:
+ - # inject credentials secret to Backstage <3>
+ extraEnvVars:
+ - name: BACKEND_SECRET
+ valueFrom:
+ secretKeyRef:
+ key: backend-secret
+ name: '{{ include "janus-idp.backend-secret-name" $ }}'
+ extraVolumeMounts:
+ - mountPath: /opt/app-root/src/dynamic-plugins-root
+ name: dynamic-plugins-root
+ - mountPath: /opt/app-root/src/postgres-crt.pem
+ name: postgres-crt # inject TLS certificate to Backstage cont. <4>
+ subPath: postgres-crt.pem
+ - mountPath: /opt/app-root/src/postgres-ca.pem
+ name: postgres-ca # inject CA certificate to Backstage cont. <5>
+ subPath: postgres-ca.pem
+ - mountPath: /opt/app-root/src/postgres-key.key
+ name: postgres-key # inject TLS private key to Backstage cont. <6>
+ subPath: postgres-key.key
+ extraVolumes:
+ - ephemeral:
+ volumeClaimTemplate:
+ spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
+ name: dynamic-plugins-root
+ - configMap:
+ defaultMode: 420
+ name: dynamic-plugins
+ optional: true
+ name: dynamic-plugins
+ - name: dynamic-plugins-npmrc
+ secret:
+ defaultMode: 420
+ optional: true
+ secretName: dynamic-plugins-npmrc
+ - name: postgres-crt
+ secret:
+ secretName: <7>
+ # ...
+----
+<1> Set the value of the `upstream.postgresql.enabled` parameter to `false` to disable creating local PostgreSQL instances.
+<2> Provide the name of the credential secret.
+<3> Provide the name of the credential secret.
+<4> Optional: Provide the name of the TLS certificate only for a TLS connection.
+<5> Optional: Provide the name of the CA certificate only for a TLS connection.
+<6> Optional: Provide the name of the TLS private key only if your TLS connection requires a private key.
+<7> Provide the name of the certificate secret if you have configured a TLS connection.
+
+. Apply the configuration changes in your Helm configuration file named `values.yaml`:
++
+[source,terminal,subs="attributes+"]
+----
+helm upgrade -n openshift-helm-charts/redhat-developer-hub -f values.yaml --version {product-chart-version}
+----
diff --git a/modules/admin/proc-configuring-postgresql-instance-using-operator.adoc b/modules/admin/proc-configuring-postgresql-instance-using-operator.adoc
new file mode 100644
index 0000000000..3389eb0b49
--- /dev/null
+++ b/modules/admin/proc-configuring-postgresql-instance-using-operator.adoc
@@ -0,0 +1,109 @@
+[id="proc-configuring-postgresql-instance-using-operator_{context}"]
+= Configuring an external PostgreSQL instance using the Operator
+
+You can configure an external PostgreSQL instance using the {product} Operator. By default, the Operator creates and manages a local instance of PostgreSQL in the same namespace where you have deployed the {product-very-short} instance. However, you can change this default setting to configure an external PostgreSQL database server, for example, Amazon Web Services (AWS) Relational Database Service (RDS) or Azure database.
+
+.Prerequisites
+
+* You are using a supported version of PostgreSQL. For more information, see the link:https://access.redhat.com/support/policy/updates/developerhub[Product life cycle page].
+* You have the following details:
+** `db-host`: Denotes your PostgreSQL instance Domain Name System (DNS) or IP address
+** `db-port`: Denotes your PostgreSQL instance port number, such as `5432`
+** `username`: Denotes the user name to connect to your PostgreSQL instance
+** `password`: Denotes the password to connect to your PostgreSQL instance
+* You have installed the {product} Operator.
+* Optional: You have a CA certificate, Transport Layer Security (TLS) private key, and TLS certificate so that you can secure your database connection by using the TLS protocol. For more information, refer to your PostgreSQL vendor documentation.
+
+[NOTE]
+====
+By default, {product-short} uses a database for each plugin and automatically creates it if none is found. You might need the `Create Database` privilege in addition to `PSQL Database` privileges for configuring an external PostgreSQL instance.
+====
+
+
+.Procedure
+
+. Optional: Create a certificate secret to configure your PostgreSQL instance with a TLS connection:
++
+[source,yaml]
+----
+cat < create -f -
+apiVersion: v1
+kind: Secret
+metadata:
+ name: <1>
+type: Opaque
+stringData:
+ postgres-ca.pem: |-
+ -----BEGIN CERTIFICATE-----
+ <2>
+ postgres-key.key: |-
+ -----BEGIN CERTIFICATE-----
+ <3>
+ postgres-crt.pem: |-
+ -----BEGIN CERTIFICATE-----
+ <4>
+ # ...
+EOF
+----
+<1> Provide the name of the certificate secret.
+<2> Provide the CA certificate key.
+<3> Optional: Provide the TLS private key.
+<4> Optional: Provide the TLS certificate key.
+
+. Create a credential secret to connect with the PostgreSQL instance:
++
+[source,yaml]
+----
+cat < create -f -
+apiVersion: v1
+kind: Secret
+metadata:
+ name: <1>
+type: Opaque
+stringData: <2>
+ POSTGRES_PASSWORD:
+ POSTGRES_PORT: ""
+ POSTGRES_USER:
+ POSTGRES_HOST:
+ PGSSLMODE: # for TLS connection <3>
+ NODE_EXTRA_CA_CERTS: # for TLS connection, e.g. /opt/app-root/src/postgres-crt.pem <4>
+EOF
+----
+<1> Provide the name of the credential secret.
+<2> Provide credential data to connect with your PostgreSQL instance.
+<3> Optional: Provide the value based on the required link:https://www.postgresql.org/docs/15/libpq-connect.html#LIBPQ-CONNECT-SSLMODE[Secure Sockets Layer (SSL) mode].
+<4> Optional: Provide the value only if you need a TLS connection for your PostgreSQL instance.
+
+. Create a `Backstage` custom resource (CR):
++
+[source,terminal]
+----
+cat < create -f -
+apiVersion: rhdh.redhat.com/v1alpha1
+kind: Backstage
+metadata:
+ name:
+spec:
+ database:
+ enableLocalDb: false <1>
+ application:
+ extraFiles:
+ mountPath: # e g /opt/app-root/src
+ secrets:
+ - name: <2>
+ key: postgres-crt.pem, postgres-ca.pem, postgres-key.key # key name as in Secret
+ extraEnvs:
+ secrets:
+ - name: <3>
+ # ...
+----
+<1> Set the value of the `enableLocalDb` parameter to `false` to disable creating local PostgreSQL instances.
+<2> Provide the name of the certificate secret if you have configured a TLS connection.
+<3> Provide the name of the credential secret that you created.
++
+[NOTE]
+====
+The environment variables listed in the `Backstage` CR work with the Operator default configuration. If you have changed the Operator default configuration, you must reconfigure the `Backstage` CR accordingly.
+====
+
+. Apply the `Backstage` CR to the namespace where you have deployed the {product-very-short} instance.
diff --git a/modules/admin/proc-configuring-proxy-in-helm-deployment.adoc b/modules/admin/proc-configuring-proxy-in-helm-deployment.adoc
new file mode 100644
index 0000000000..cb679b0940
--- /dev/null
+++ b/modules/admin/proc-configuring-proxy-in-helm-deployment.adoc
@@ -0,0 +1,48 @@
+[id="proc-configuring-proxy-in-helm-deployment_{context}"]
+= Configuring proxy information in Helm deployment
+
+For Helm-based deployment, either a developer or a cluster administrator with permissions to create resources in the cluster can configure the proxy variables in a `values.yaml` Helm configuration file.
+
+.Prerequisites
+
+* You have installed the {product} application.
+
+.Procedure
+
+. Set the proxy information in your Helm configuration file:
++
+[source,yaml]
+----
+upstream:
+ backstage:
+ extraEnvVars:
+ - name: HTTP_PROXY
+ value: ''
+ - name: HTTPS_PROXY
+ value: ''
+ - name: NO_PROXY
+ value: ''
+----
++
+Where,
+
+``:: Denotes a variable that you must replace with the HTTP proxy URL.
+``:: Denotes a variable that you must replace with the HTTPS proxy URL.
+``:: Denotes a variable that you must replace with comma-separated URLs, which you want to exclude from proxying, for example, `foo.com,baz.com`.
++
+.Example: Setting proxy variables using Helm Chart
+
+[source,yaml]
+----
+upstream:
+ backstage:
+ extraEnvVars:
+ - name: HTTP_PROXY
+ value: 'http://10.10.10.105:3128'
+ - name: HTTPS_PROXY
+ value: 'http://10.10.10.106:3128'
+ - name: NO_PROXY
+ value: 'localhost,example.org'
+----
+
+. Save the configuration changes.
diff --git a/modules/admin/proc-configuring-proxy-in-operator-deployment.adoc b/modules/admin/proc-configuring-proxy-in-operator-deployment.adoc
new file mode 100644
index 0000000000..8e741ec5ff
--- /dev/null
+++ b/modules/admin/proc-configuring-proxy-in-operator-deployment.adoc
@@ -0,0 +1,80 @@
+[id="proc-configuring-proxy-in-operator-deployment_{context}"]
+= Configuring proxy information in Operator deployment
+
+For Operator-based deployment, the approach you use for proxy configuration is based on your role:
+
+* As a cluster administrator with access to the Operator namespace, you can configure the proxy variables in the Operator's default ConfigMap file. This configuration applies the proxy settings to all the users of the Operator.
+* As a developer, you can configure the proxy variables in a custom resource (CR) file. This configuration applies the proxy settings to the {product-very-short} application created from that CR.
+
+.Prerequisites
+
+* You have installed the {product} application.
+
+.Procedure
+
+. Perform one of the following steps based on your role:
+
+* As an administrator, set the proxy information in the Operator's default ConfigMap file:
++
+.. Search for a ConfigMap file named `backstage-default-config` in the default namespace `rhdh-operator` and open it.
+.. Find the `deployment.yaml` key.
+.. Set the value of the `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` environment variables in the `Deployment` spec as shown in the following example:
++
+.Example: Setting proxy variables in a ConfigMap file
+[source,yaml]
+----
+# Other fields omitted
+ deployment.yaml: |-
+ apiVersion: apps/v1
+ kind: Deployment
+ spec:
+ template:
+ spec:
+ # Other fields omitted
+ initContainers:
+ - name: install-dynamic-plugins
+ # command omitted
+ env:
+ - name: NPM_CONFIG_USERCONFIG
+ value: /opt/app-root/src/.npmrc.dynamic-plugins
+ - name: HTTP_PROXY
+ value: 'http://10.10.10.105:3128'
+ - name: HTTPS_PROXY
+ value: 'http://10.10.10.106:3128'
+ - name: NO_PROXY
+ value: 'localhost,example.org'
+ # Other fields omitted
+ containers:
+ - name: backstage-backend
+ # Other fields omitted
+ env:
+ - name: APP_CONFIG_backend_listen_port
+ value: "7007"
+ - name: HTTP_PROXY
+ value: 'http://10.10.10.105:3128'
+ - name: HTTPS_PROXY
+ value: 'http://10.10.10.106:3128'
+ - name: NO_PROXY
+ value: 'localhost,example.org'
+----
+
+
+* As a developer, set the proxy information in your custom resource (CR) file as shown in the following example:
++
+.Example: Setting proxy variables in a CR file
+[source, yaml]
+----
+spec:
+ # Other fields omitted
+ application:
+ extraEnvs:
+ envs:
+ - name: HTTP_PROXY
+ value: 'http://10.10.10.105:3128'
+ - name: HTTPS_PROXY
+ value: 'http://10.10.10.106:3128'
+ - name: NO_PROXY
+ value: 'localhost,example.org'
+----
+
+. Save the configuration changes.
diff --git a/modules/admin/proc-customizing-telemetry-segment-using-helm.adoc b/modules/admin/proc-customizing-telemetry-segment-using-helm.adoc
new file mode 100644
index 0000000000..3b61cbb981
--- /dev/null
+++ b/modules/admin/proc-customizing-telemetry-segment-using-helm.adoc
@@ -0,0 +1,42 @@
+[id="proc-customizing-telemetry-segment-using-helm_{context}"]
+= Customizing telemetry Segment source using the Helm Chart
+
+You can configure integration with your Segment source by using the Helm Chart.
+
+.Prerequisites
+
+* You have logged in as an administrator in the {ocp-short} web console.
+* You have installed {product} on {ocp-short} using the Helm Chart.
+
+.Procedure
+
+. In the *Developer* perspective of the {ocp-short} web console, go to the *Helm* view to see the list of Helm releases.
+. Click the *overflow* menu on the Helm release that you want to use and select *Upgrade*.
+. Use either the *Form* view or *YAML* view to edit the Helm configuration:
+** Using *Form view*
++
+.. Expand *Root Schema → Backstage Chart Schema → Backstage Parameters → Backstage container environment variables*.
+.. Click the *Add Backstage container environment variables* link.
+.. Enter the name and value of the Segment key.
++
+image::rhdh/segment-source-helm.png[]
+
+.. Click *Upgrade*.
+
+** Using *YAML view*
++
+.. Add the following YAML code in your Helm configuration file:
++
+[source,yaml]
+----
+# ...
+upstream:
+ backstage:
+ extraEnvVars:
+ - name: SEGMENT_WRITE_KEY
+ value: # <1>
+# ...
+----
+<1> Replace `` with a unique identifier for your Segment source.
+
+.. Click *Upgrade*.
diff --git a/modules/admin/proc-customizing-telemetry-segment-using-operator.adoc b/modules/admin/proc-customizing-telemetry-segment-using-operator.adoc
new file mode 100644
index 0000000000..b3ecb6a502
--- /dev/null
+++ b/modules/admin/proc-customizing-telemetry-segment-using-operator.adoc
@@ -0,0 +1,28 @@
+[id="proc-customizing-telemetry-segment-using-operator_{context}"]
+= Customizing telemetry Segment source using the Operator
+
+You can configure integration with your Segment source by using the Operator.
+
+.Prerequisites
+
+* You have logged in as an administrator in the {ocp-short} web console.
+* You have installed {product} on {ocp-short} using the Operator.
+
+.Procedure
+
+. Add the following YAML code in your `Backstage` custom resource (CR):
++
+[source,yaml]
+----
+# ...
+spec:
+ application:
+ extraEnvs:
+ envs:
+ - name: SEGMENT_WRITE_KEY
+ value: # <1>
+# ...
+----
+<1> Replace `` with a unique identifier for your Segment source.
+
+. Save the configuration changes.
diff --git a/modules/admin/proc-disabling-telemetry-using-helm.adoc b/modules/admin/proc-disabling-telemetry-using-helm.adoc
new file mode 100644
index 0000000000..625bb9e58b
--- /dev/null
+++ b/modules/admin/proc-disabling-telemetry-using-helm.adoc
@@ -0,0 +1,61 @@
+[id="proc-disabling-telemetry-using-helm_{context}"]
+= Disabling telemetry data collection using the Helm Chart
+
+You can disable the telemetry data collection feature by using the Helm Chart.
+
+.Prerequisites
+
+* You have logged in as an administrator in the {ocp-short} web console.
+* You have installed {product} on {ocp-short} using the Helm Chart.
+
+.Procedure
+
+. In the *Developer* perspective of the {ocp-short} web console, go to the *Helm* view to see the list of Helm releases.
+. Click the *overflow* menu on the Helm release that you want to use and select *Upgrade*.
++
+[NOTE]
+====
+You can also create a new Helm release by clicking the *Create* button and edit the configuration to disable telemetry.
+====
+
+. Use either the *Form* view or *YAML* view to edit the Helm configuration:
+** Using *Form view*
++
+.. Expand *Root Schema → global → Dynamic plugins configuration. → List of dynamic plugins that should be installed in the backstage application*.
+.. Click the *Add list of dynamic plugins that should be installed in the backstage application.* link.
+
+.. Perform one of the following steps:
++
+*** If you have not configured the plugin, add the following value in the *Package specification of the dynamic plugin to install. It should be usable by the npm pack command.* field:
++
+`./dynamic-plugins/dist/janus-idp-backstage-plugin-analytics-provider-segment`
++
+image::rhdh/disabling-telemetry.png[]
++
+*** If you have configured the plugin, find the *Package specification of the dynamic plugin to install. It should be usable by the npm pack command.* field with the `./dynamic-plugins/dist/janus-idp-backstage-plugin-analytics-provider-segment` value.
+
+.. Select the *Disable the plugin* checkbox.
+.. Click *Upgrade*.
+
+** Using *YAML view*
++
+.. Perform one of the following steps:
++
+*** If you have not configured the plugin, add the following YAML code in your `values.yaml` Helm configuration file:
++
+[source,yaml]
+----
+# ...
+global:
+ dynamic:
+ plugins:
+ - package: './dynamic-plugins/dist/janus-idp-backstage-plugin-analytics-provider-segment'
+ disabled: true
+# ...
+----
++
+*** If you have configured the plugin, search it in your Helm configuration and set the value of the `plugins.disabled` parameter to `true`.
+
+.. Click *Upgrade*.
+
+
diff --git a/modules/admin/proc-disabling-telemetry-using-operator.adoc b/modules/admin/proc-disabling-telemetry-using-operator.adoc
new file mode 100644
index 0000000000..66c07efb10
--- /dev/null
+++ b/modules/admin/proc-disabling-telemetry-using-operator.adoc
@@ -0,0 +1,49 @@
+[id="proc-disabling-telemetry-using-operator_{context}"]
+= Disabling telemetry data collection using the Operator
+
+You can disable the telemetry data collection feature by using the Operator.
+
+.Prerequisites
+
+* You have logged in as an administrator in the {ocp-short} web console.
+* You have installed {product} on {ocp-short} using the Operator.
+
+.Procedure
+
+. Perform one of the following steps:
++
+* If you have created the `dynamic-plugins-rhdh` ConfigMap file and not configured the `analytics-provider-segment` plugin, add the plugin to the list of plugins and set its `plugins.disabled` parameter to `true`.
++
+* If you have created the `dynamic-plugins-rhdh` ConfigMap file and configured the `analytics-provider-segment` plugin, search the plugin in the list of plugins and set its `plugins.disabled` parameter to `true`.
++
+* If you have not created the ConfigMap file, create it with the following YAML code:
++
+[source,yaml]
+----
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: dynamic-plugins-rhdh
+data:
+ dynamic-plugins.yaml: |
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: './dynamic-plugins/dist/janus-idp-backstage-plugin-analytics-provider-segment'
+ disabled: true
+----
+
+. Set the value of the `dynamicPluginsConfigMapName` parameter to the name of the ConfigMap file in your `Backstage` custom resource:
++
+[source,yaml]
+----
+# ...
+spec:
+ application:
+ dynamicPluginsConfigMapName: dynamic-plugins-rhdh
+# ...
+----
+
+. Save the configuration changes.
+
+
diff --git a/modules/admin/proc-enabling-telemetry-using-helm.adoc b/modules/admin/proc-enabling-telemetry-using-helm.adoc
new file mode 100644
index 0000000000..ce3a39d315
--- /dev/null
+++ b/modules/admin/proc-enabling-telemetry-using-helm.adoc
@@ -0,0 +1,58 @@
+[id="proc-enabling-telemetry-using-helm_{context}"]
+= Enabling telemetry data collection using the Helm Chart
+
+You can enable the telemetry data collection feature by using the Helm Chart.
+
+.Prerequisites
+
+* You have logged in as an administrator in the {ocp-short} web console.
+* You have installed {product} on {ocp-short} using the Helm Chart.
+
+.Procedure
+
+. In the *Developer* perspective of the {ocp-short} web console, go to the *Helm* view to see the list of Helm releases.
+. Click the *overflow* menu on the Helm release that you want to use and select *Upgrade*.
++
+[NOTE]
+====
+You can also create a new Helm release by clicking the *Create* button and edit the configuration to enable telemetry.
+====
+
+. Use either the *Form* view or *YAML* view to edit the Helm configuration:
+** Using *Form view*
++
+.. Expand *Root Schema → global → Dynamic plugins configuration. → List of dynamic plugins that should be installed in the backstage application*.
+.. Click the *Add list of dynamic plugins that should be installed in the backstage application.* link.
+
+.. Perform one of the following steps:
++
+*** If you have not configured the plugin, add the following value in the *Package specification of the dynamic plugin to install. It should be usable by the npm pack command.* field:
++
+`./dynamic-plugins/dist/janus-idp-backstage-plugin-analytics-provider-segment`
++
+*** If you have configured the plugin, find the *Package specification of the dynamic plugin to install. It should be usable by the npm pack command.* field with the `./dynamic-plugins/dist/janus-idp-backstage-plugin-analytics-provider-segment` value.
+
+.. Clear the *Disable the plugin* checkbox.
+.. Click *Upgrade*.
+
+** Using *YAML view*
++
+.. Perform one of the following steps:
++
+*** If you have not configured the plugin, add the following YAML code in your Helm configuration file:
++
+[source,yaml]
+----
+# ...
+global:
+ dynamic:
+ plugins:
+ - package: './dynamic-plugins/dist/janus-idp-backstage-plugin-analytics-provider-segment'
+ disabled: false
+# ...
+----
++
+*** If you have configured the plugin, search it in your Helm configuration and set the value of the `plugins.disabled` parameter to `false`.
+
+.. Click *Upgrade*.
+
diff --git a/modules/admin/proc-enabling-telemetry-using-operator.adoc b/modules/admin/proc-enabling-telemetry-using-operator.adoc
new file mode 100644
index 0000000000..404ae4b2e6
--- /dev/null
+++ b/modules/admin/proc-enabling-telemetry-using-operator.adoc
@@ -0,0 +1,48 @@
+[id="proc-enabling-telemetry-using-operator_{context}"]
+= Enabling telemetry data collection using the Operator
+
+You can enable the telemetry data collection feature by using the Operator.
+
+.Prerequisites
+
+* You have logged in as an administrator in the {ocp-short} web console.
+* You have installed {product} on {ocp-short} using the Operator.
+
+.Procedure
+
+. Perform one of the following steps:
++
+* If you have created the `dynamic-plugins-rhdh` ConfigMap file and not configured the `analytics-provider-segment` plugin, add the plugin to the list of plugins and set its `plugins.disabled` parameter to `false`.
++
+* If you have created the `dynamic-plugins-rhdh` ConfigMap file and configured the `analytics-provider-segment` plugin, search the plugin in the list of plugins and set its `plugins.disabled` parameter to `false`.
++
+* If you have not created the ConfigMap file, create it with the following YAML code:
++
+[source,yaml]
+----
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: dynamic-plugins-rhdh
+data:
+ dynamic-plugins.yaml: |
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: './dynamic-plugins/dist/janus-idp-backstage-plugin-analytics-provider-segment'
+ disabled: false
+----
+
+. Set the value of the `dynamicPluginsConfigMapName` parameter to the name of the ConfigMap file in your `Backstage` custom resource:
++
+[source,yaml]
+----
+# ...
+spec:
+ application:
+ dynamicPluginsConfigMapName: dynamic-plugins-rhdh
+# ...
+----
+
+. Save the configuration changes.
+
diff --git a/modules/admin/proc-migrating-databases-to-an-external-server.adoc b/modules/admin/proc-migrating-databases-to-an-external-server.adoc
new file mode 100644
index 0000000000..520ec78a07
--- /dev/null
+++ b/modules/admin/proc-migrating-databases-to-an-external-server.adoc
@@ -0,0 +1,129 @@
+[id="proc-migrating-databases-to-an-external-server_{context}"]
+= Migrating local databases to an external database server using the Operator
+
+By default, {product} hosts the data for each plugin in a PostgreSQL database. When you fetch the list of databases, you might see multiple databases based on the number of plugins configured in {product-short}. You can migrate the data from an {product-very-short} instance hosted on a local PostgreSQL server to an external PostgreSQL service, such as AWS RDS, Azure database, or Crunchy database. To migrate the data from each {product-very-short} instance, you can use PostgreSQL utilities, such as link:https://www.postgresql.org/docs/current/app-pgdump.html[`pg_dump`] with link:https://www.postgresql.org/docs/current/app-psql.html[`psql`] or link:https://www.pgadmin.org/[`pgAdmin`].
+
+[NOTE]
+====
+The following procedure uses a database copy script to do a quick migration.
+====
+
+.Prerequisites
+
+* You have installed the link:https://www.postgresql.org/docs/current/app-pgdump.html[`pg_dump`] and link:https://www.postgresql.org/docs/current/app-psql.html[`psql`] utilities on your local machine.
+* For data export, you have the PGSQL user privileges to make a full dump of local databases.
+* For data import, you have the PGSQL admin privileges to create an external database and populate it with database dumps.
+
+.Procedure
+
+. Configure port forwarding for the local PostgreSQL database pod by running the following command on a terminal:
++
+[source,terminal]
+----
+oc port-forward -n :
+----
+Where:
+* The `` variable denotes the name of a PostgreSQL pod with the format `backstage-psql--<_index>`.
+* The `` variable denotes the port of your choice to forward PostgreSQL data to.
+* The `` variable denotes the local PostgreSQL instance port, such as `5432`.
++
+.Example: Configuring port forwarding
+[source,terminal]
+----
+oc port-forward -n developer-hub backstage-psql-developer-hub-0 15432:5432
+----
+
+. Make a copy of the following `db_copy.sh` script and edit the details based on your configuration:
++
+[source,bash]
+----
+#!/bin/bash
+
+to_host= <1>
+to_port=5432 <2>
+to_user=postgres <3>
+
+from_host=127.0.0.1 <4>
+from_port=15432 <5>
+from_user=postgres <6>
+
+allDB=("backstage_plugin_app" "backstage_plugin_auth" "backstage_plugin_catalog" "backstage_plugin_permission" "backstage_plugin_scaffolder" "backstage_plugin_search") <7>
+
+for db in ${!allDB[@]};
+do
+ db=${allDB[$db]}
+ echo Copying database: $db
+ PGPASSWORD=$TO_PSW psql -h $to_host -p $to_port -U $to_user -c "create database $db;"
+ pg_dump -h $from_host -p $from_port -U $from_user -d $db | PGPASSWORD=$TO_PSW psql -h $to_host -p $to_port -U $to_user -d $db
+done
+----
+<1> The destination host name, for example, `.rds.amazonaws.com`.
+<2> The destination port, such as `5432`.
+<3> The destination server username, for example, `postgres`.
+<4> The source host name, such as `127.0.0.1`.
+<5> The source port number, such as the `` variable.
+<6> The source server username, for example, `postgres`.
+<7> The name of databases to import in double quotes separated by spaces, for example, `("backstage_plugin_app" "backstage_plugin_auth" "backstage_plugin_catalog" "backstage_plugin_permission" "backstage_plugin_scaffolder" "backstage_plugin_search")`.
+
+. Create a destination database for copying the data:
++
+[source,terminal]
+----
+/bin/bash TO_PSW= /path/to/db_copy.sh <1>
+----
+<1> The `` variable denotes the password to connect to the destination database.
++
+[NOTE]
+====
+You can stop port forwarding when the copying of the data is complete. For more information about handling large databases and using the compression tools, see the link:https://www.postgresql.org/docs/current/backup-dump.html#BACKUP-DUMP-LARGE[Handling Large Databases] section on the PostgreSQL website.
+====
+
+. Reconfigure your `Backstage` custom resource (CR). For more information, see link:{LinkAdminGuide}#proc-configuring-postgresql-instance-using-operator_admin-rhdh[Configuring an external PostgreSQL instance using the Operator].
+. Check that the following code is present at the end of your `Backstage` CR after reconfiguration:
++
+[source,yaml]
+----
+# ...
+spec:
+ database:
+ enableLocalDb: false
+ application:
+ # ...
+ extraFiles:
+ secrets:
+ - name:
+ key: postgres-crt.pem # key name as in Secret
+ extraEnvs:
+ secrets:
+ - name:
+# ...
+----
++
+[NOTE]
+====
+Reconfiguring the `Backstage` CR deletes the corresponding `StatefulSet` and `Pod` objects, but does not delete the `PersistenceVolumeClaim` object. Use the following command to delete the local `PersistenceVolumeClaim` object:
+
+[source,terminal]
+----
+oc -n developer-hub delete pvc
+----
+where, the `` variable is in the `data-` format.
+====
+
+. Apply the configuration changes.
+
+
+.Verification
+
+. Verify that your {product-very-short} instance is running with the migrated data and does not contain the local PostgreSQL database by running the following command:
++
+[source,terminal]
+----
+oc get pods -n
+----
+
+. Check the output for the following details:
+* The `backstage-developer-hub-xxx` pod is in running state.
+* The `backstage-psql-developer-hub-0` pod is not available.
++
+You can also verify these details using the *Topology* view in the {ocp-short} web console.
diff --git a/modules/admin/proc-rhdh-deployment-config.adoc b/modules/admin/proc-rhdh-deployment-config.adoc
new file mode 100644
index 0000000000..47b44e98b0
--- /dev/null
+++ b/modules/admin/proc-rhdh-deployment-config.adoc
@@ -0,0 +1,150 @@
+// Module included in:
+// title-admin.adoc
+
+[id="proc-rhdh-deployment-config_{context}"]
+= Configuring {product} deployment
+
+The {product} operator exposes a `rhdh.redhat.com/v1alpha2` API Version of its Custom Resource Definition (CRD). This CRD exposes a generic `spec.deployment.patch` field, which gives you full control over the {product-short} Deployment resource. This field can be a fragment of the standard `apps.Deployment` Kubernetes object.
+
+.Procedure
+
+. Create a {product-short} Custom Resource Definition with the following fields:
+
+--
+.Example
+[source, yaml]
+----
+apiVersion: rhdh.redhat.com/v1alpha2
+kind: Backstage
+metadata:
+ name: developer-hub
+spec:
+ deployment:
+ patch:
+ spec:
+ template:
+----
+
+`labels`::
+Add labels to the {product-short} pod.
++
+.Example adding the label `my=true`
+[source, yaml]
+----
+apiVersion: rhdh.redhat.com/v1alpha2
+kind: Backstage
+metadata:
+ name: developer-hub
+spec:
+ deployment:
+ patch:
+ spec:
+ template:
+ metadata:
+ labels:
+ my: true
+----
+
+`volumes`::
+Add an additional volume named `my-volume` and mount it under `/my/path` in the {product-short} application container.
++
+.Example additional volume
+[source, yaml]
+----
+apiVersion: rhdh.redhat.com/v1alpha2
+kind: Backstage
+metadata:
+ name: developer-hub
+spec:
+ deployment:
+ patch:
+ spec:
+ template:
+ spec:
+ containers:
+ - name: backstage-backend
+ volumeMounts:
+ - mountPath: /my/path
+ name: my-volume
+ volumes:
+ - ephemeral:
+ volumeClaimTemplate:
+ spec:
+ storageClassName: "special"
+ name: my-volume
+----
++
+Replace the default `dynamic-plugins-root` volume with a persistent volume claim (PVC) named `dynamic-plugins-root`. Note the `$patch: replace` directive, otherwise a new volume will be added.
++
+.Example `dynamic-plugins-root` volume replacement
+[source, yaml]
+----
+apiVersion: rhdh.redhat.com/v1alpha2
+kind: Backstage
+metadata:
+ name: developer-hub
+spec:
+ deployment:
+ patch:
+ spec:
+ template:
+ spec:
+ volumes:
+ - $patch: replace
+ name: dynamic-plugins-root
+ persistentVolumeClaim:
+ claimName: dynamic-plugins-root
+----
+
+`cpu` request::
+
+Set the CPU request for the {product-short} application container to 250m.
++
+.Example CPU request
+[source, yaml]
+----
+apiVersion: rhdh.redhat.com/v1alpha2
+kind: Backstage
+metadata:
+ name: developer-hub
+spec:
+ deployment:
+ patch:
+ spec:
+ template:
+ spec:
+ containers:
+ - name: backstage-backend
+ resources:
+ requests:
+ cpu: 250m
+----
+
+`my-sidecar` container::
+
+Add a new `my-sidecar` sidecar container into the {product-short} Pod.
++
+.Example side car container
+[source, yaml]
+----
+apiVersion: rhdh.redhat.com/v1alpha2
+kind: Backstage
+metadata:
+ name: developer-hub
+spec:
+ deployment:
+ patch:
+ spec:
+ template:
+ spec:
+ containers:
+ - name: my-sidecar
+ image: quay.io/my-org/my-sidecar:latest
+----
+
+--
+
+[role="_additional-resources"]
+.Additional resources
+
+* To learn more about merging, see link:https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md#basic-patch-format[Strategic Merge Patch].
\ No newline at end of file
diff --git a/modules/admin/proc-rhdh-monitoring-logging-aks.adoc b/modules/admin/proc-rhdh-monitoring-logging-aks.adoc
new file mode 100644
index 0000000000..83d5bed36f
--- /dev/null
+++ b/modules/admin/proc-rhdh-monitoring-logging-aks.adoc
@@ -0,0 +1,54 @@
+[id='proc-rhdh-monitoring-logging-aks_{context}']
+= Monitoring and logging with Azure Kubernetes Services (AKS) in {product}
+
+Monitoring and logging are integral aspects of managing and maintaining Azure Kubernetes Services (AKS) in {product}. With features like Managed Prometheus Monitoring and Azure Monitor integration, administrators can efficiently monitor resource utilization, diagnose issues, and ensure the reliability of their containerized workloads.
+
+To enable Managed Prometheus Monitoring, use the `-enable-azure-monitor-metrics` option within either the `az aks create` or `az aks update` command, depending on whether you're creating a new cluster or updating an existing one, such as:
+
+[source,bash]
+----
+az aks create/update --resource-group --name --enable-azure-monitor-metrics
+----
+
+The previous command installs the metrics add-on, which gathers https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/prometheus-metrics-overview[Prometheus metrics]. Using the previous command, you can enable monitoring of Azure resources through both native Azure Monitor metrics and Prometheus metrics. You can also view the results in the portal under *Monitoring -> Insights*. For more information, see https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/monitor-azure-resource[Monitor Azure resources with Azure Monitor].
+
+Furthermore, metrics from both the Managed Prometheus service and Azure Monitor can be accessed through Azure Managed Grafana service. For more information, see https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/azure-monitor-workspace-manage?tabs=azure-portal#link-a-grafana-workspace[Link a Grafana workspace] section.
+
+By default, Prometheus uses the minimum ingesting profile, which optimizes ingestion volume and sets default configurations for scrape frequency, targets, and metrics collected. The default settings can be customized through custom configuration. Azure offers various methods, including using different ConfigMaps, to provide scrape configuration and other metric add-on settings. For more information about default configuration, see https://learn.microsoft.com/en-us/azure/azure-monitor/containers/prometheus-metrics-scrape-default[Default Prometheus metrics configuration in Azure Monitor] and https://learn.microsoft.com/en-us/azure/azure-monitor/containers/prometheus-metrics-scrape-configuration?tabs=CRDConfig%2CCRDScrapeConfig[Customize scraping of Prometheus metrics in Azure Monitor managed service for Prometheus] documentation.
+
+== Viewing logs with Azure Kubernetes Services (AKS)
+
+You can access live data logs generated by Kubernetes objects and collect log data in Container Insights within AKS.
+
+.Prerequisites
+
+* You have deployed {product-short} on {aks-short}.
+
+For more information, see xref:{installing-on-aks-book-url}#assembly-install-rhdh-aks[{installing-on-aks-book-title}].
+
+.Procedure
+
+View live logs from your {product-short} instance::
++
+--
+. Navigate to the Azure Portal.
+. Search for the resource group `` and locate your AKS cluster ``.
+. Select *Kubernetes resources -> Workloads* from the menu.
+. Select the `-developer-hub` (in case of Helm Chart installation) or `-backstage` (in case of Operator-backed installation) deployment.
+. Click *Live Logs* in the left menu.
+. Select the pod.
++
+NOTE: There must be only single pod.
+
+Live log data is collected and displayed.
+--
+
+View real-time log data from the Container Engine::
++
+--
+. Navigate to the Azure Portal.
+. Search for the resource group `` and locate your AKS cluster ``.
+. Select *Monitoring* -> *Insights* from the menu.
+. Go to the *Containers* tab.
+. Find the backend-backstage container and click it to view real-time log data as it's generated by the Container Engine.
+--
diff --git a/modules/admin/proc-rhdh-monitoring-logging-aws.adoc b/modules/admin/proc-rhdh-monitoring-logging-aws.adoc
new file mode 100644
index 0000000000..2dee4d2303
--- /dev/null
+++ b/modules/admin/proc-rhdh-monitoring-logging-aws.adoc
@@ -0,0 +1,149 @@
+[id='proc-rhdh-monitoring-logging-aws_{context}']
+= Monitoring and logging with Amazon Web Services (AWS) in {product}
+
+In the {product}, monitoring and logging are facilitated through Amazon Web Services (AWS) integration. With features like Amazon CloudWatch for real-time monitoring and Amazon Prometheus for comprehensive logging, you can ensure the reliability, scalability, and compliance of your {product-short} application hosted on AWS infrastructure.
+
+This integration enables you to oversee, diagnose, and refine your applications in the Red Hat ecosystem, leading to an improved development and operational journey.
+
+== Monitoring with Amazon Prometheus
+
+{product} provides Prometheus metrics related to the running application. For more information about enabling or deploying Prometheus for EKS clusters, see https://docs.aws.amazon.com/eks/latest/userguide/prometheus.html[Prometheus metrics] in the Amazon documentation.
+
+To monitor {product-short} using https://aws.amazon.com/prometheus/[Amazon Prometheus], you need to create an Amazon managed service for the Prometheus workspace and configure the ingestion of the Developer Hub Prometheus metrics. For more information, see https://docs.aws.amazon.com/prometheus/latest/userguide/AMP-onboard-create-workspace.html[Create a workspace] and https://docs.aws.amazon.com/prometheus/latest/userguide/AMP-onboard-ingest-metrics.html[Ingest Prometheus metrics to the workspace] sections in the Amazon documentation.
+
+After ingesting Prometheus metrics into the created workspace, you can configure the metrics scraping to extract data from pods based on specific pod annotations.
+
+=== Configuring annotations for monitoring
+
+You can configure the annotations for monitoring in both Helm deployment and Operator-backed deployment.
+
+Helm deployment::
++
+--
+To annotate the backstage pod for monitoring, update your `values.yaml` file as follows:
+
+[source,yaml]
+----
+upstream:
+ backstage:
+ # --- TRUNCATED ---
+ podAnnotations:
+ prometheus.io/scrape: 'true'
+ prometheus.io/path: '/metrics'
+ prometheus.io/port: '7007'
+ prometheus.io/scheme: 'http'
+----
+--
+
+Operator-backed deployment::
++
+--
+.Procedure
+
+. As an administrator of the operator, edit the default configuration to add Prometheus annotations as follows:
++
+[source,bash]
+----
+# Update OPERATOR_NS accordingly
+OPERATOR_NS=rhdh-operator
+kubectl edit configmap backstage-default-config -n "${OPERATOR_NS}"
+----
+
+. Find the `deployment.yaml` key in the ConfigMap and add the annotations to the `spec.template.metadata.annotations` field as follows:
++
+[source,yaml]
+----
+deployment.yaml: |-
+ apiVersion: apps/v1
+ kind: Deployment
+ # --- truncated ---
+ spec:
+ template:
+ # --- truncated ---
+ metadata:
+ labels:
+ rhdh.redhat.com/app: # placeholder for 'backstage-'
+ # --- truncated ---
+ annotations:
+ prometheus.io/scrape: 'true'
+ prometheus.io/path: '/metrics'
+ prometheus.io/port: '7007'
+ prometheus.io/scheme: 'http'
+ # --- truncated ---
+----
+
+. Save your changes.
+--
+
+.Verification
+
+To verify if the scraping works:
+
+. Use `kubectl` to port-forward the Prometheus console to your local machine as follows:
++
+[source,bash]
+----
+kubectl --namespace=prometheus port-forward deploy/prometheus-server 9090
+----
+
+. Open your web browser and navigate to `pass:c[http://localhost:9090]` to access the Prometheus console.
+. Monitor relevant metrics, such as `process_cpu_user_seconds_total`.
+
+== Logging with Amazon CloudWatch logs
+
+Logging within the {product} relies on the https://github.com/winstonjs/winston[winston library]. By default, logs at the debug level are not recorded. To activate debug logs, you must set the environment variable `LOG_LEVEL` to debug in your {product} instance.
+
+=== Configuring the application log level
+
+You can configure the application log level in both Helm deployment and Operator-backed deployment.
+
+Helm deployment::
++
+--
+To update the logging level, add the environment variable `LOG_LEVEL` to your Helm chart's `values.yaml` file:
+
+[source,yaml]
+----
+upstream:
+ backstage:
+ # --- Truncated ---
+ extraEnvVars:
+ - name: LOG_LEVEL
+ value: debug
+----
+--
+
+Operator-backed deployment::
++
+--
+You can modify the logging level by including the environment variable `LOG_LEVEL` in your custom resource as follows:
+
+[source,yaml]
+----
+spec:
+ # Other fields omitted
+ application:
+ extraEnvs:
+ envs:
+ - name: LOG_LEVEL
+ value: debug
+----
+--
+
+=== Retrieving logs from Amazon CloudWatch
+
+The CloudWatch Container Insights are used to capture logs and metrics for Amazon EKS. For more information, see https://docs.aws.amazon.com/prescriptive-guidance/latest/implementing-logging-monitoring-cloudwatch/kubernetes-eks-logging.html[Logging for Amazon EKS] documentation.
+
+To capture the logs and metrics, https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-setup-EKS-addon.html[install the Amazon CloudWatch Observability EKS add-on] in your cluster. Following the setup of Container Insights, you can access container logs using Logs Insights or Live Tail views.
+
+CloudWatch names the log group where all container logs are consolidated in the following manner:
+
+`/aws/containerinsights//application`
+
+Following is an example query to retrieve logs from the Developer Hub instance:
+
+[source,sql]
+----
+fields @timestamp, @message, kubernetes.container_name
+| filter kubernetes.container_name in ["install-dynamic-plugins", "backstage-backend"]
+----
diff --git a/modules/admin/proc-using-aws-cognito-auth-provider.adoc b/modules/admin/proc-using-aws-cognito-auth-provider.adoc
new file mode 100644
index 0000000000..a35ff5404e
--- /dev/null
+++ b/modules/admin/proc-using-aws-cognito-auth-provider.adoc
@@ -0,0 +1,219 @@
+[id='proc-using-aws-cognito-auth-provider_{context}']
+= Using Amazon Cognito as an authentication provider in {product}
+
+In this section, Amazon Cognito is an AWS service for adding an authentication layer to {product-short}. You can sign in directly to the {product-short} using a user pool or fedarate through a third-party identity provider.
+
+Although Amazon Cognito is not part of the core authentication providers for the Developer Hub, it can be integrated using the generic OpenID Connect (OIDC) provider.
+
+You can configure your {product-short} in both Helm Chart and Operator-backed deployments.
+
+.Prerequisites
+
+* You have a User Pool or you have created a new one. For more information about user pools, see https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html?icmpid=docs_cognito_console_help_panel[Amazon Cognito user pools] documentation.
++
+[NOTE]
+====
+Ensure that you have noted the AWS region where the user pool is located and the user pool ID.
+====
+
+* You have created an App Client within your user pool for integrating the hosted UI. For more information, see https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-integration.html#cognito-user-pools-create-an-app-integration[Setting up the hosted UI with the Amazon Cognito console].
++
+--
+When setting up the hosted UI using the Amazon Cognito console, ensure to make the following adjustments:
+
+. In the *Allowed callback URL(s)* section, include the URL `pass:c[https:///api/auth/oidc/handler/frame]`. Ensure to replace `` with your {product-short} application's URL, such as, `my.rhdh.example.com`.
+
+. Similarly, in the *Allowed sign-out URL(s)* section, add `pass:c[https://]`. Replace `` with your {product-short} application's URL, such as `my.rhdh.example.com`.
+
+. Under *OAuth 2.0 grant types*, select *Authorization code grant* to return an authorization code.
+
+. Under *OpenID Connect scopes*, ensure to select at least the following scopes:
+
+** OpenID
+** Profile
+** Email
+--
+
+Helm deployment::
++
+--
+.Procedure
+
+. Edit or create your custom `app-config-rhdh` ConfigMap as follows:
++
+[source,yaml]
+----
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: app-config-rhdh
+data:
+ "app-config-rhdh.yaml": |
+ # --- Truncated ---
+ app:
+ title: Red Hat Developer Hub
+
+ signInPage: oidc
+ auth:
+ environment: production
+ session:
+ secret: ${AUTH_SESSION_SECRET}
+ providers:
+ oidc:
+ production:
+ clientId: ${AWS_COGNITO_APP_CLIENT_ID}
+ clientSecret: ${AWS_COGNITO_APP_CLIENT_SECRET}
+ metadataUrl: ${AWS_COGNITO_APP_METADATA_URL}
+ callbackUrl: ${AWS_COGNITO_APP_CALLBACK_URL}
+ scope: 'openid profile email'
+ prompt: auto
+----
+
+. Edit or create your custom `secrets-rhdh` Secret using the following template:
++
+[source,yaml]
+----
+apiVersion: v1
+kind: Secret
+metadata:
+ name: secrets-rhdh
+stringData:
+ AUTH_SESSION_SECRET: "my super auth session secret - change me!!!"
+ AWS_COGNITO_APP_CLIENT_ID: "my-aws-cognito-app-client-id"
+ AWS_COGNITO_APP_CLIENT_SECRET: "my-aws-cognito-app-client-secret"
+ AWS_COGNITO_APP_METADATA_URL: "https://cognito-idp.[region].amazonaws.com/[userPoolId]/.well-known/openid-configuration"
+ AWS_COGNITO_APP_CALLBACK_URL: "https://[rhdh_dns]/api/auth/oidc/handler/frame"
+----
+
+. Add references of both the ConfigMap and Secret resources in your `values.yaml` file:
++
+[source,yaml]
+----
+upstream:
+ backstage:
+ image:
+ pullSecrets:
+ - rhdh-pull-secret
+ podSecurityContext:
+ fsGroup: 2000
+ extraAppConfig:
+ - filename: app-config-rhdh.yaml
+ configMapRef: app-config-rhdh
+ extraEnvVarsSecrets:
+ - secrets-rhdh
+----
+
+. Upgrade the Helm deployment:
++
+[source,terminal,subs="attributes+"]
+----
+helm upgrade rhdh \
+ openshift-helm-charts/redhat-developer-hub \
+ [--version {product-chart-version}] \
+ --values /path/to/values.yaml
+----
+--
+
+Operator-backed deployment::
++
+--
+. Add the following code to your `app-config-rhdh` ConfigMap:
++
+[source,yaml]
+----
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: app-config-rhdh
+data:
+ "app-config-rhdh.yaml": |
+ # --- Truncated ---
+
+ signInPage: oidc
+ auth:
+ # Production to disable guest user login
+ environment: production
+ # Providing an auth.session.secret is needed because the oidc provider requires session support.
+ session:
+ secret: ${AUTH_SESSION_SECRET}
+ providers:
+ oidc:
+ production:
+ # See https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-oidc-provider/config.d.ts
+ clientId: ${AWS_COGNITO_APP_CLIENT_ID}
+ clientSecret: ${AWS_COGNITO_APP_CLIENT_SECRET}
+ metadataUrl: ${AWS_COGNITO_APP_METADATA_URL}
+ callbackUrl: ${AWS_COGNITO_APP_CALLBACK_URL}
+ # Minimal set of scopes needed. Feel free to add more if needed.
+ scope: 'openid profile email'
+
+ # Note that by default, this provider will use the 'none' prompt which assumes that your are already logged on in the IDP.
+ # You should set prompt to:
+ # - auto: will let the IDP decide if you need to log on or if you can skip login when you have an active SSO session
+ # - login: will force the IDP to always present a login form to the user
+ prompt: auto
+----
+
+. Add the following code to your `secrets-rhdh` Secret:
++
+[source,yaml]
+----
+apiVersion: v1
+kind: Secret
+metadata:
+ name: secrets-rhdh
+stringData:
+ # --- Truncated ---
+
+ # TODO: Change auth session secret.
+ AUTH_SESSION_SECRET: "my super auth session secret - change me!!!"
+
+ # TODO: user pool app client ID
+ AWS_COGNITO_APP_CLIENT_ID: "my-aws-cognito-app-client-id"
+
+ # TODO: user pool app client Secret
+ AWS_COGNITO_APP_CLIENT_SECRET: "my-aws-cognito-app-client-secret"
+
+ # TODO: Replace region and user pool ID
+ AWS_COGNITO_APP_METADATA_URL: "https://cognito-idp.[region].amazonaws.com/[userPoolId]/.well-known/openid-configuration"
+
+ # TODO: Replace
+ AWS_COGNITO_APP_CALLBACK_URL: "https://[rhdh_dns]/api/auth/oidc/handler/frame"
+----
+
+. Ensure your Custom Resource contains references to both the `app-config-rhdh` ConfigMap and `secrets-rhdh` Secret:
++
+[source,yaml,subs="attributes+"]
+----
+apiVersion: rhdh.redhat.com/v1alpha1
+kind: Backstage
+metadata:
+ # TODO: this the name of your {product-short} instance
+ name: my-rhdh
+spec:
+ application:
+ imagePullSecrets:
+ - "rhdh-pull-secret"
+ route:
+ enabled: false
+ appConfig:
+ configMaps:
+ - name: "app-config-rhdh"
+ extraEnvs:
+ secrets:
+ - name: "secrets-rhdh"
+----
+
+. Optional: If you have an existing {product-short} instance backed by the Custom Resource and you have not edited it, you can manually delete the {product-short} deployment to recreate it using the operator. Run the following command to delete the {product-short} deployment:
++
+[source,bash]
+----
+kubectl delete deployment -l app.kubernetes.io/instance=
+----
+--
+
+.Verification
+
+. Navigate to your {product-short} web URL and sign in using OIDC authentication, which prompts you to authenticate through the configured AWS Cognito user pool.
+
+. Once logged in, access *Settings* and verify user details.
diff --git a/modules/admin/proc-using-azure-auth-provider.adoc b/modules/admin/proc-using-azure-auth-provider.adoc
new file mode 100644
index 0000000000..285c02060f
--- /dev/null
+++ b/modules/admin/proc-using-azure-auth-provider.adoc
@@ -0,0 +1,220 @@
+[id='proc-using-azure-auth-provider_{context}']
+
+= Using Microsoft Azure as an authentication provider in {product}
+
+The `core-plugin-api` package in {product-short} comes integrated with Microsoft Azure authentication provider, authenticating signing in using Azure OAuth.
+
+.Prerequisites
+* You have deployed {product-short} on AKS.
+
+For more information, see xref:{installing-on-aks-book-url}#assembly-install-rhdh-aks[Installing {product} on {aks-name} ({aks-short})].
+
+* You have created registered your application in Azure portal. For more information, see https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app[Register an application with the Microsoft identity platform].
+
+== Using Microsoft Azure as an authentication provider in Helm deployment
+
+You can use Microsoft Azure as an authentication provider in {product}, when installed using the Helm Chart.
+
+For more information, see xref:{installing-on-aks-book-url}#proc-rhdh-deploy-aks-helm_assembly-install-rhdh-aks[Deploying {product-short} on {aks-short} with the Helm chart].
+
+.Procedure
+
+. After the application is registered, note down the following:
++
+--
+** `clientId`: Application (client) ID, found under App *Registration -> Overview*.
+** `clientSecret`: Secret, found under *App Registration -> Certificates & secrets (create new if needed).
+** `tenantId`: Directory (tenant) ID, found under *App Registration -> Overview*.
+--
+
+. Ensure the following fragment is included in your {product-short} ConfigMap:
++
+--
+[source,yaml]
+----
+auth:
+ environment: production
+ providers:
+ microsoft:
+ production:
+ clientId: ${AZURE_CLIENT_ID}
+ clientSecret: ${AZURE_CLIENT_SECRET}
+ tenantId: ${AZURE_TENANT_ID}
+ domainHint: ${AZURE_TENANT_ID}
+ additionalScopes:
+ - Mail.Send
+----
+You can either create a new file or add it to an existing one.
+--
+
+. Apply the ConfigMap to your Kubernetes cluster:
++
+--
+[source,bash]
+----
+kubectl -n apply -f .yaml
+----
+--
+
+. Create or reuse an existing Secret containing Azure credentials and add the following fragment:
++
+--
+[source,yaml]
+----
+stringData:
+ AZURE_CLIENT_ID:
+ AZURE_CLIENT_SECRET:
+ AZURE_TENANT_ID:
+----
+--
+
+. Apply the secret to your Kubernetes cluster:
++
+--
+[source,bash]
+----
+kubectl -n apply -f .yaml
+----
+--
+
+. Ensure your `values.yaml` file references the previously created ConfigMap and Secret:
++
+--
+[source,yaml]
+----
+upstream:
+ backstage:
+ ...
+ extraAppConfig:
+ - filename: ...
+ configMapRef:
+ extraEnvVarsSecrets:
+ -
+----
+--
+
+. Optional: If the Helm Chart is already installed, upgrade it:
++
+--
+[source,terminal,subs="attributes+"]
+----
+helm -n upgrade -f redhat-developer/backstage --version {product-chart-version}
+----
+--
+
+. Optional: If your `rhdh.yaml` file is not changed, for example, you only updated the ConfigMap and Secret referenced from it, refresh your {product-short} deployment by removing the corresponding pods:
++
+--
+[source,bash]
+----
+kubectl -n delete pods -l backstage.io/app=backstage-
+----
+--
+
+== Using Microsoft Azure as an authentication provider in Operator-backed deployment
+
+You can use Microsoft Azure as an authentication provider in {product}, when installed using the Operator.
+
+For more information, see xref:{installing-on-ocp-book-url}#proc-install-operator_assembly-install-rhdh-ocp-operator[Installing {product} on {ocp-short} with the Operator].
+
+.Procedure
+
+. After the application is registered, note down the following:
++
+--
+** `clientId`: Application (client) ID, found under App *Registration -> Overview*.
+** `clientSecret`: Secret, found under *App Registration -> Certificates & secrets (create new if needed).
+** `tenantId`: Directory (tenant) ID, found under *App Registration -> Overview*.
+--
+
+. Ensure the following fragment is included in your {product-short} ConfigMap:
++
+--
+[source,yaml]
+----
+auth:
+ environment: production
+ providers:
+ microsoft:
+ production:
+ clientId: ${AZURE_CLIENT_ID}
+ clientSecret: ${AZURE_CLIENT_SECRET}
+ tenantId: ${AZURE_TENANT_ID}
+ domainHint: ${AZURE_TENANT_ID}
+ additionalScopes:
+ - Mail.Send
+----
+You can either create a new file or add it to an existing one.
+--
+
+. Apply the ConfigMap to your Kubernetes cluster:
++
+--
+[source,bash]
+----
+kubectl -n apply -f .yaml
+----
+--
+
+. Create or reuse an existing Secret containing Azure credentials and add the following fragment:
++
+--
+[source,yaml]
+----
+stringData:
+ AZURE_CLIENT_ID:
+ AZURE_CLIENT_SECRET:
+ AZURE_TENANT_ID:
+----
+--
+
+. Apply the secret to your Kubernetes cluster:
++
+--
+[source,bash]
+----
+kubectl -n apply -f .yaml
+----
+--
+
+. Ensure your Custom Resource manifest contains references to the previously created ConfigMap and Secret:
++
+--
+[source,yaml]
+----
+apiVersion: rhdh.redhat.com/v1alpha1
+kind: Backstage
+metadata:
+ name:
+spec:
+ application:
+ imagePullSecrets:
+ - rhdh-pull-secret
+ route:
+ enabled: false
+ appConfig:
+ configMaps:
+ - name:
+ extraEnvs:
+ secrets:
+ - name:
+----
+--
+
+. Apply your Custom Resource manifest:
++
+--
+[source,bash]
+----
+kubectl -n apply -f rhdh.yaml
+----
+--
+
+. Optional: If your `rhdh.yaml` file is not changed, for example, you only updated the ConfigMap and Secret referenced from it, refresh your {product-short} deployment by removing the corresponding pods:
++
+--
+[source,bash]
+----
+kubectl -n delete pods -l backstage.io/app=backstage-
+----
+--
diff --git a/modules/admin/ref-customizing-telemetry-segment.adoc b/modules/admin/ref-customizing-telemetry-segment.adoc
new file mode 100644
index 0000000000..d5c386f31a
--- /dev/null
+++ b/modules/admin/ref-customizing-telemetry-segment.adoc
@@ -0,0 +1,12 @@
+[id="customizing-telemetry-segment_{context}"]
+= Customizing telemetry Segment source
+
+
+The `analytics-provider-segment` plugin sends the collected telemetry data to {company-name} by default. However, you can configure a new Segment source that receives telemetry data based on your needs. For configuration, you need a unique Segment write key that points to the Segment source.
+
+[NOTE]
+====
+By configuring a new Segment source, you can collect and analyze the same set of data that is mentioned in the link:{LinkAdminGuide}#assembly-rhdh-telemetry[Telemetry data collection] section. You might also require to create your own telemetry data collection notice for your application users.
+====
+
+
diff --git a/modules/admin/ref-disabling-telemetry.adoc b/modules/admin/ref-disabling-telemetry.adoc
new file mode 100644
index 0000000000..66bf4470e1
--- /dev/null
+++ b/modules/admin/ref-disabling-telemetry.adoc
@@ -0,0 +1,6 @@
+[id="disabling-telemetry-data-collection_{context}"]
+= Disabling telemetry data collection in {product-very-short}
+
+To disable telemetry data collection, you must disable the `analytics-provider-segment` plugin either using the Helm Chart or the {product} Operator configuration.
+
+
diff --git a/modules/admin/ref-enabling-telemetry.adoc b/modules/admin/ref-enabling-telemetry.adoc
new file mode 100644
index 0000000000..9df4622324
--- /dev/null
+++ b/modules/admin/ref-enabling-telemetry.adoc
@@ -0,0 +1,5 @@
+[id="enabling-telemetry-data-collection_{context}"]
+= Enabling telemetry data collection in {product-very-short}
+
+The telemetry data collection feature is enabled by default. However, if you have disabled the feature and want to re-enable it, you must enable the `analytics-provider-segment` plugin either by using the Helm Chart or the {product} Operator configuration.
+
diff --git a/modules/authentication/proc-authenticationg-with-the-guest-user-on-a-helm-based-installation.adoc b/modules/authentication/proc-authenticationg-with-the-guest-user-on-a-helm-based-installation.adoc
new file mode 100644
index 0000000000..aa116e6546
--- /dev/null
+++ b/modules/authentication/proc-authenticationg-with-the-guest-user-on-a-helm-based-installation.adoc
@@ -0,0 +1,32 @@
+:_mod-docs-content-type: PROCEDURE
+[id="authenticating-with-the-guest-user-on-a-helm-based-installation_{context}"]
+= Authenticating with the Guest user on a Helm-based installation
+
+On a Helm-based installation, you can configure {product-short} to log in as a Guest user and access {product-short} features.
+
+.Prerequisites
+* You link:https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}#Install%20and%20Upgrade[Installed {product-short} by using the Helm Chart].
+
+.Procedure
+* To enable the guest user in your {product-short} custom configuration, link:https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/administration_guide_for_red_hat_developer_hub/index#proc-add-custom-app-file-openshift-helm_admin-rhdh[configure your {product} Helm Chart] with following content:
++
+.{product} Helm Chart configuration fragment
+[source,yaml]
+----
+upstream:
+ backstage:
+ appConfig:
+ app:
+ baseUrl: 'https://{{- include "janus-idp.hostname" . }}'
+ auth:
+ environment: development
+ providers:
+ guest:
+ dangerouslyAllowOutsideDevelopment: true
+----
+
+.Verification
+. Go to the {product-short} login page.
+. To log in with the Guest user account, click **Enter** in the **Guest** tile.
+. In the {product-short} **Settings** page, your profile name is **Guest**.
+. You can use {product-short} features.
diff --git a/modules/authentication/proc-authenticationg-with-the-guest-user-on-an-operator-based-installation.adoc b/modules/authentication/proc-authenticationg-with-the-guest-user-on-an-operator-based-installation.adoc
new file mode 100644
index 0000000000..958e73542c
--- /dev/null
+++ b/modules/authentication/proc-authenticationg-with-the-guest-user-on-an-operator-based-installation.adoc
@@ -0,0 +1,28 @@
+:_mod-docs-content-type: PROCEDURE
+[id="authenticating-with-the-guest-user-on-an-operator-based-installation_{context}"]
+= Authenticating with the Guest user on an Operator-based installation
+
+After an Operator-based installation, you can configure {product-short} to log in as a Guest user and access {product-short} features.
+
+.Prerequisites
+* You link:[installed {product-short} by using the Operator].
+* You link:https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/administration_guide_for_red_hat_developer_hub/index#proc-add-custom-app-config-file-ocp-operator_admin-rhdh[added a custom {product-short} application configuration], and have sufficient permissions to modify it.
+
+.Procedure
+* To enable the guest user in your {product-short} custom configuration, link:https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/administration_guide_for_red_hat_developer_hub/index#proc-add-custom-app-config-file-ocp-operator_admin-rhdh[edit your {product-short} application configuration] with following content:
++
+.`app-config-rhdh.yaml` fragment
+[source,yaml]
+----
+auth:
+ environment: development
+ providers:
+ guest:
+ dangerouslyAllowOutsideDevelopment: true
+----
+
+.Verification
+. Go to the {product-short} login page.
+. To log in with the Guest user account, click **Enter** in the **Guest** tile.
+. In the {product-short} **Settings** page, your profile name is **Guest**.
+. You can use {product-short} features.
diff --git a/modules/authentication/proc-creating-a-custom-transformer-to-provision-users-from-rhsso-to-the-software-catalog.adoc b/modules/authentication/proc-creating-a-custom-transformer-to-provision-users-from-rhsso-to-the-software-catalog.adoc
new file mode 100644
index 0000000000..802be18d07
--- /dev/null
+++ b/modules/authentication/proc-creating-a-custom-transformer-to-provision-users-from-rhsso-to-the-software-catalog.adoc
@@ -0,0 +1,92 @@
+[id="creating-a-custom-transformer-to-provision-users-from-rhsso-to-the-software-catalog"]
+= Creating a custom transformer to provision users from {rhsso-brand-name} ({rhsso}) to the software catalog
+
+To customize how {rhsso} users and groups are mapped to {product} entities, you can create a backend module that uses the `keycloakTransformerExtensionPoint` to provide custom user and group transformers for the Keycloak backend.
+
+.Prerequisites
+* You have xref:provisioning-users-from-rhsso-to-the-software-catalog[enabled provisioning users from {rhsso-brand-name} ({rhsso}) to the software catalog].
+
+.Procedure
+. Create a new backend module with the `yarn new` command.
+
+. Add your custom user and group transformers to the `keycloakTransformerExtensionPoint`.
+
++
+The following is an example of how the backend module can be defined:
++
+.`plugins/____/src/module.ts`
+[source,javascript]
+----
+import {
+ GroupTransformer,
+ keycloakTransformerExtensionPoint,
+ UserTransformer,
+} from '@janus-idp/backstage-plugin-keycloak-backend';
+
+const customGroupTransformer: GroupTransformer = async (
+ entity, // entity output from default parser
+ realm, // Keycloak realm name
+ groups, // Keycloak group representation
+) => {
+ /* apply transformations */
+ return entity;
+};
+const customUserTransformer: UserTransformer = async (
+ entity, // entity output from default parser
+ user, // Keycloak user representation
+ realm, // Keycloak realm name
+ groups, // Keycloak group representation
+) => {
+ /* apply transformations */
+ return entity;
+};
+
+export const keycloakBackendModuleTransformer = createBackendModule({
+ pluginId: 'catalog',
+ moduleId: 'keycloak-transformer',
+ register(reg) {
+ reg.registerInit({
+ deps: {
+ keycloak: keycloakTransformerExtensionPoint,
+ },
+ async init({ keycloak }) {
+ keycloak.setUserTransformer(customUserTransformer);
+ keycloak.setGroupTransformer(customGroupTransformer);
+ /* highlight-add-end */
+ },
+ });
+ },
+});
+----
++
+[IMPORTANT]
+====
+The module's `pluginId` must be set to `catalog` to match the `pluginId` of the `keycloak-backend`; otherwise, the module fails to initialize.
+====
+
+. Install this new backend module into your {product-short} backend.
++
+[source,javascript]
+----
+backend.add(import(backstage-plugin-catalog-backend-module-keycloak-transformer))
+----
+
+.Verification
+
+* {product-short} imports the users and groups each time when started.
+Check the console logs to verify that the synchronization is completed.
++
+.Successful synchronization example:
+[source,json]
+----
+{"class":"KeycloakOrgEntityProvider","level":"info","message":"Read 3 Keycloak users and 2 Keycloak groups in 1.5 seconds. Committing...","plugin":"catalog","service":"backstage","taskId":"KeycloakOrgEntityProvider:default:refresh","taskInstanceId":"bf0467ff-8ac4-4702-911c-380270e44dea","timestamp":"2024-09-25 13:58:04"}
+{"class":"KeycloakOrgEntityProvider","level":"info","message":"Committed 3 Keycloak users and 2 Keycloak groups in 0.0 seconds.","plugin":"catalog","service":"backstage","taskId":"KeycloakOrgEntityProvider:default:refresh","taskInstanceId":"bf0467ff-8ac4-4702-911c-380270e44dea","timestamp":"2024-09-25 13:58:04"}
+----
+
+* After the first import is complete, navigate to the *Catalog* page and select **User** to view the list of users.
+
+* When you select a user, you see the information imported from {rhsso}.
+
+* You can select a group, view the list, and access or review the information imported from {rhsso}.
+
+* You can log in with an {rhsso} account.
diff --git a/modules/authentication/proc-enabling-authentication-with-github.adoc b/modules/authentication/proc-enabling-authentication-with-github.adoc
new file mode 100644
index 0000000000..b4157bdec0
--- /dev/null
+++ b/modules/authentication/proc-enabling-authentication-with-github.adoc
@@ -0,0 +1,168 @@
+[id="enabling-authentication-with-github"]
+= Enabling authentication with GitHub
+
+To authenticate users with GitHub, enable the GitHub authentication provider in {product}.
+
+.Prerequisites
+* You have link:https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html/administration_guide_for_red_hat_developer_hub/assembly-add-custom-app-file-openshift_admin-rhdh[added a custom {product-short} application configuration], and have sufficient permissions to modify it.
+* You have sufficient permissions in GitHub to create and manage a link:https://docs.github.com/en/apps/overview[GitHub App].
+
+.Procedure
+. To allow {product-short} to authenticate with GitHub, create a GitHub App.
+Opt for a GitHub App instead of an OAuth app to use fine-grained permissions, gain more control over which repositories the application can access, and use short-lived tokens.
+
+.. link:https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app[Register a GitHub App] with the following configuration:
++
+* *GitHub App name*: Enter a unique name identifying your GitHub App, such as __<{product}>__-____.
+* *Homepage URL*: Your {product-short} URL: `pass:c,a,q[{my-product-url}]`.
+* *Authorization callback URL*: Your {product-short} authentication backend URL: `pass:c,a,q[{my-product-url}/api/auth/github/handler/frame]`.
+* *Webhook URL*: Your {product-short} URL: `pass:c,a,q[{my-product-url}]`.
+* *Webhook secret*: Provide a strong secret.
+* *Repository permissions*:
+** Enable `Read-only` access to:
+*** *Administration*
+*** *Commit statuses*
+*** *Contents*
+*** *Dependabot alerts*
+*** *Deployments*
+*** *Pull Requests*
+*** *Webhooks*
++
+TIP: If you plan to make changes using the GitHub API, ensure that `Read and write` permissions are enabled instead of `Read-only`.
+
+** Toggle other permissions as per your needs.
+
+* *Organization permissions*:
+** Enable `Read-only` access to *Members*.
+
+* For *Where can this GitHub App be installed?*, select `Only on this account`.
+
+.. In the *General* -> *Clients secrets* section, click *Generate a new client secret*.
+
+.. In the *General* -> *Private keys* section, click *Generate a private key*.
+
+.. In the *Install App* tab, choose an account to install your GitHub App on.
+
+.. Save the following values for the next step:
+
+* **App ID**
+* **Client ID**
+* **Client secret**
+* **Private key**
+* **Webhook secret**
+
+. To add your GitHub credentials to your {product-short} secrets, edit your {product-short} secrets, such as `secrets-rhdh`, and add the following key/value pairs:
++
+`AUTH_GITHUB_APP_ID`:: Enter the saved **App ID**.
+`AUTH_GITHUB_CLIENT_ID`:: Enter the saved **Client ID**.
+`GITHUB_HOST_DOMAIN`:: Enter your GitHub host domain: `pass:c[https://github.com]` unless you are using GitHub Enterprise.
+`GITHUB_ORGANIZATION`:: Enter your GitHub organization name, such as `____'.
+`GITHUB_ORG_URL`:: Enter `$GITHUB_HOST_DOMAIN/$GITHUB_ORGANIZATION`.
+`GITHUB_CLIENT_SECRET`:: Enter the saved **Client Secret**.
+`GITHUB_PRIVATE_KEY_FILE`:: Enter the saved **Private key**.
+`GITHUB_WEBHOOK_URL`:: Enter your {product-short} URL: `pass:c,a,q[{my-product-url}]`.
+`GITHUB_WEBHOOK_SECRET`:: Enter the saved *Webhook secret*.
+
+. To set up the GitHub authentication provider and enable integration with the GitHub API in your {product-short} custom configuration, edit your custom {product-short} ConfigMap such as `app-config-rhdh`, and add the following lines to the `app-config-rhdh.yaml` content:
++
+--
+.`app-config-rhdh.yaml` fragment with mandatory fields to enable authentication with GitHub
+[source,yaml]
+----
+auth:
+ environment: production
+ providers:
+ github:
+ production:
+ clientId: ${AUTH_GITHUB_CLIENT_ID}
+ clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
+integrations:
+ github:
+ - host: ${GITHUB_HOST_DOMAIN}
+ apps:
+ - appId: ${AUTH_GITHUB_APP_ID}
+ clientId: ${AUTH_GITHUB_CLIENT_ID}
+ clientSecret: ${GITHUB_CLIENT_SECRET}
+ webhookUrl: ${GITHUB_WEBHOOK_URL}
+ webhookSecret: ${GITHUB_WEBHOOK_SECRET}
+ privateKey: |
+ ${GITHUB_PRIVATE_KEY_FILE}
+signInPage: github
+----
+
+`environment: production`::
+Mark the environment as `production` to hide the Guest login in the {product-short} home page.
+
+`clientId`, `clientSecret`, `host`, `appId`, `webhookUrl`, `webhookSecret`, `privateKey`::
+Use the {product-short} application information that you have created in GitHub and configured in OpenShift as secrets.
+
+`sigInPage: github`::
+To enable the GitHub provider as default sign-in provider.
+
+Optional: Consider adding the following optional fields:
+
+`dangerouslyAllowSignInWithoutUserInCatalog: true`::
+To enable authentication without requiring to provision users in the {product-short} software catalog.
++
+WARNING: Use `dangerouslyAllowSignInWithoutUserInCatalog` to explore {product-short} features, but do not use it in production.
++
+.`app-config-rhdh.yaml` fragment with optional field to allow authenticating users absent from the software catalog
+[source,yaml]
+----
+auth:
+ environment: production
+ providers:
+ github:
+ production:
+ clientId: ${AUTH_GITHUB_CLIENT_ID}
+ clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
+integrations:
+ github:
+ - host: ${GITHUB_HOST_DOMAIN}
+ apps:
+ - appId: ${AUTH_GITHUB_APP_ID}
+ clientId: ${AUTH_GITHUB_CLIENT_ID}
+ clientSecret: ${GITHUB_CLIENT_SECRET}
+ webhookUrl: ${GITHUB_WEBHOOK_URL}
+ webhookSecret: ${GITHUB_WEBHOOK_SECRET}
+ privateKey: |
+ ${GITHUB_PRIVATE_KEY_FILE}
+signInPage: github
+dangerouslyAllowSignInWithoutUserInCatalog: true
+----
+
+`callbackUrl`::
+The callback URL that GitHub uses when initiating an OAuth flow, such as: ____.
+Define it when {product-short} is not the immediate receiver, such as in cases when you use one OAuth app for many {product-short} instances.
++
+.`app-config-rhdh.yaml` fragment with optional `enterpriseInstanceUrl` field
+[source,yaml,subs="+quotes"]
+----
+auth:
+ providers:
+ github:
+ production:
+ callbackUrl: ____
+----
+
+`enterpriseInstanceUrl`::
+Your GitHub Enterprise URL.
+Requires you defined the `GITHUB_HOST_DOMAIN` secret in the previous step.
++
+.`app-config-rhdh.yaml` fragment with optional `enterpriseInstanceUrl` field
+[source,yaml,subs="+quotes"]
+----
+auth:
+ providers:
+ github:
+ production:
+ enterpriseInstanceUrl: ${GITHUB_HOST_DOMAIN}
+----
+
+--
+
+.Verification
+. Go to the {product-short} login page.
+. Your {product-short} sign-in page displays *Sign in using GitHub* and the Guest user sign-in is disabled.
+. Log in with GitHub.
+
diff --git a/modules/authentication/proc-enabling-authentication-with-microsoft-azure.adoc b/modules/authentication/proc-enabling-authentication-with-microsoft-azure.adoc
new file mode 100644
index 0000000000..517c38c40c
--- /dev/null
+++ b/modules/authentication/proc-enabling-authentication-with-microsoft-azure.adoc
@@ -0,0 +1,147 @@
+[id="enabling-authentication-with-microsoft-azure"]
+= Enabling authentication with Microsoft Azure
+
+{product} includes a Microsoft Azure authentication provider that can authenticate users by using OAuth.
+
+.Prerequisites
+. You have the permission to register an application in Microsoft Azure.
+. You link:https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html-single/administration_guide_for_red_hat_developer_hub/index#assembly-add-custom-app-file-openshift_admin-rhdh[added a custom {product-short} application configuration].
+
+.Procedure
+. To allow {product-short} to authenticate with Microsoft Azure, link:https://learn.microsoft.com/en-us/entra/identity-platform/scenario-web-app-sign-user-app-registration?tabs=aspnetcore#register-an-app-by-using-the-azure-portal[create an OAuth application in Microsoft Azure].
+
+.. In the Azure portal go to link:https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade[*App registrations*], create a **New registration** with the configuration:
++
+**Name**:: The application name in Azure, such as ____.
+
+.. On the *Home > App registrations > ____ > Manage > Authentication* page, *Add a platform*, with the following configuration:
+
+*Redirect URI*:: Enter the backend authentication URI set in {product-short}: `pass:c,a,q[{my-product-url}/api/auth/microsoft/handler/frame]`
+*Front-channel logout URL*:: Leave blank.
+*Implicit grant and hybrid flows*:: Leave all checkboxes cleared.
+
+.. On the *Home > App registrations > ____ > Manage > API permissions* page, *Add a Permission*, then add the following *Delegated permission* for the *Microsoft Graph API*:
++
+* `email`
+* `offline_access`
+* `openid`
+* `profile`
+* `User.Read`
+* Optional custom scopes for the Microsoft Graph API that you define both in this section and in the {product-short} configuration (`app-config-rhdh.yaml`).
++
+[NOTE]
+====
+Your company might require you to grant admin consent for these permissions.
+Even if your company does not require admin consent, you might do so as it means users do not need to individually consent the first time they access backstage.
+To grant administrator consent, a directory administrator must go to the link:https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/user-admin-consent-overview[admin consent] page and click *Grant admin consent for COMPANY NAME*.
+====
+
+
+.. On the *Home > App registrations > ____ > Manage > Certificates & Secrets* page, in the *Client secrets* tab, create a *New client secret*.
+
+.. Save for the next step:
+- **Directory (tenant) ID**
+- **Application (client) ID**
+- **Application (client) secret**
+
+. To add your Microsoft Azure credentials to {product-short}, add the following key/value pairs to your {product-short} secrets, such as `secrets-rhdh`:
++
+`AUTH_AZURE_TENANT_ID`:: Enter your saved *Directory (tenant) ID*.
+`AUTH_AZURE_CLIENT_ID`:: Enter your saved *Application (client) ID*.
+`AUTH_AZURE_CLIENT_SECRET`:: Enter your saved *Application (client) secret*.
+
+. Set up the Microsoft Azure authentication provider in your {product-short} custom configuration, such as `app-config-rhdh`:
++
+--
+.`app-config-rhdh.yaml` fragment
+[source,yaml,subs="+quotes,+attributes"]
+----
+auth:
+ environment: production
+ providers:
+ microsoft:
+ production:
+ clientId: ${AUTH_AZURE_CLIENT_ID}
+ clientSecret: ${AUTH_AZURE_CLIENT_SECRET}
+ tenantId: ${AUTH_AZURE_TENANT_ID}
+signInPage: microsoft
+----
+
+`environment: production`::
+Mark the environment as production to hide the **Guest** login in the {product-short} home page.
+
+`clientId`, `clientSecret` and `tenantId`::
+Use the {product-short} application information that you have created in Microsoft Azure and configured in OpenShift as secrets.
+
+`signInPage: microsoft`::
+Enable the Microsoft Azure provider as default sign-in provider.
+
+Optional: Consider adding following optional fields:
+
+`dangerouslyAllowSignInWithoutUserInCatalog: true`::
++
+To enable authentication without requiring to provision users in the {product-short} software catalog.
++
+WARNING: Use `dangerouslyAllowSignInWithoutUserInCatalog` to explore {product-short} features, but do not use it in production.
++
+.`app-config-rhdh.yaml` fragment with optional field to allow authenticating users absent from the software catalog
+[source,yaml]
+----
+auth:
+ environment: production
+ providers:
+ microsoft:
+ production:
+ clientId: ${AUTH_AZURE_CLIENT_ID}
+ clientSecret: ${AUTH_AZURE_CLIENT_SECRET}
+ tenantId: ${AUTH_AZURE_TENANT_ID}
+signInPage: microsoft
+dangerouslyAllowSignInWithoutUserInCatalog: true
+----
+
+`domainHint`::
+Optional for single-tenant applications.
+You can reduce login friction for users with accounts in multiple tenants by automatically filtering out accounts from other tenants.
+If you want to use this parameter for a single-tenant application, uncomment and enter the tenant ID.
+If your application registration is multi-tenant, leave this parameter blank.
+For more information, see link:https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/home-realm-discovery-policy[Home Realm Discovery].
++
+.`app-config-rhdh.yaml` fragment with optional `domainHint` field
+[source,yaml,subs="+quotes,+attributes"]
+----
+auth:
+ environment: production
+ providers:
+ microsoft:
+ production:
+ domainHint: ${AUTH_AZURE_TENANT_ID}
+----
+
+`additionalScopes`::
+Optional for additional scopes.
+To add scopes for the application registration, uncomment and enter the list of scopes that you want to add.
+The default and mandatory value lists: `'openid', 'offline_access', 'profile', 'email', 'User.Read'`.
++
+.`app-config-rhdh.yaml` fragment with optional `additionalScopes` field
+[source,yaml,subs="+quotes,+attributes"]
+----
+auth:
+ environment: production
+ providers:
+ microsoft:
+ production:
+ additionalScopes:
+ - Mail.Send
+----
+--
+
+[NOTE]
+====
+This step is optional for environments with outgoing access restrictions, such as firewall rules.
+ If your environment has such restrictions, ensure that your {product-very-short} backend can access the following hosts:
+
+* `login.microsoftonline.com`: For obtaining and exchanging authorization codes and access tokens.
+
+* `graph.microsoft.com`: For retrieving user profile information (as referenced in the source code).
+If this host is unreachable, you might see an _Authentication failed, failed to fetch user profile_ error when attempting to log in.
+====
diff --git a/modules/authentication/proc-enabling-authentication-with-rhsso.adoc b/modules/authentication/proc-enabling-authentication-with-rhsso.adoc
new file mode 100644
index 0000000000..c8850771a1
--- /dev/null
+++ b/modules/authentication/proc-enabling-authentication-with-rhsso.adoc
@@ -0,0 +1,172 @@
+[id="enabling-authentication-with-rhsso"]
+= Enabling authentication with {rhsso-brand-name} ({rhsso})
+
+To authenticate users with Red Hat Single Sign-On ({rhsso}), enable the OpenID Connect (OIDC) authentication provider in {product}.
+
+
+.Prerequisites
+* You link:https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html/administration_guide_for_red_hat_developer_hub/assembly-add-custom-app-file-openshift_admin-rhdh[added a custom {product-short} application configuration], and have sufficient permissions to modify it.
+* You have sufficient permissions in {rhsso} to create and manage a realm.
+
+.Procedure
+. To allow {product-short} to authenticate with {rhsso}, complete the steps in {rhsso}, to link:https://docs.redhat.com/en/documentation/red_hat_single_sign-on/7.6/html-single/getting_started_guide/index#realms-apps_[create a realm and a user] and link:https://docs.redhat.com/en/documentation/red_hat_single_sign-on/7.6/html-single/getting_started_guide/index#registering-app_[register the {product-short} application]:
+
+.. Use an existing realm, or link:https://docs.redhat.com/en/documentation/red_hat_single_sign-on/7.6/html-single/getting_started_guide/index#create-realm_[create a realm], with a distinctive **Name** such as ____.
+Save the value for the next step:
+* **{rhsso} realm base URL**, such as: ____/auth/realms/____.
+
+.. To register your {product-short} in {rhsso}, in the created realm, link:https://docs.redhat.com/en/documentation/red_hat_single_sign-on/7.6/html-single/getting_started_guide/index#registering-app_[create a Client ID], with:
+... **Client ID**: A distinctive client ID, such as __<{product-very-short}>__.
+... **Valid redirect URIs**: Set to the OIDC handler URL: `https://____/api/auth/oidc/handler/frame`.
+... Navigate to the **Credentials** tab and copy the **Client secret**.
+... Save the values for the next step:
+* **Client ID**
+* **Client Secret**
+
+.. To prepare for the verification steps, in the same realm, get the credential information for an existing user or link:https://docs.redhat.com/en/documentation/red_hat_single_sign-on/7.6/html-single/getting_started_guide/index#create-user_[create a user]. Save the user credential information for the verification steps.
+
+. To add your {rhsso} credentials to your {product-short} secrets, edit your {product-short} secrets, such as `secrets-rhdh`, and add the following key/value pairs:
++
+`AUTH_OIDC_CLIENT_ID`:: Enter the saved **Client ID**.
+`AUTH_OIDC_CLIENT_SECRET`:: Enter the saved **Client Secret**.
+`AUTH_OIDC_METADATA_URL`:: Enter the saved **{rhsso} realm base URL**.
+
+. To set up the {rhsso} authentication provider in your {product-short} custom configuration, edit your custom {product-short} ConfigMap such as `app-config-rhdh`, and add the following lines to the `app-config-rhdh.yaml` content:
++
+--
+.`app-config-rhdh.yaml` fragment with mandatory fields to enable authentication with {rhsso}
+[source,yaml]
+----
+auth:
+ environment: production
+ providers:
+ oidc:
+ production:
+ metadataUrl: ${AUTH_OIDC_METADATA_URL}
+ clientId: ${AUTH_OIDC_CLIENT_ID}
+ clientSecret: ${AUTH_OIDC_CLIENT_SECRET}
+signInPage: oidc
+----
+
+`environment: production`::
+Mark the environment as `production` to hide the Guest login in the {product-short} home page.
+
+`metadataUrl`, `clientId`, `clientSecret`::
+To configure the OIDC provider with your secrets.
+
+`sigInPage: oidc`::
+To enable the OIDC provider as default sign-in provider.
+
+
+Optional: Consider adding the following optional fields:
+
+`dangerouslyAllowSignInWithoutUserInCatalog: true`::
++
+--
+To enable authentication without requiring to provision users in the {product-short} software catalog.
++
+WARNING: Use this option to explore {product-short} features, but do not use it in production.
++
+.`app-config-rhdh.yaml` fragment with optional field to allow authenticating users absent from the software catalog
+[source,yaml]
+----
+auth:
+ environment: production
+ providers:
+ oidc:
+ production:
+ metadataUrl: ${AUTH_OIDC_METADATA_URL}
+ clientId: ${AUTH_OIDC_CLIENT_ID}
+ clientSecret: ${AUTH_OIDC_CLIENT_SECRET}
+signInPage: oidc
+dangerouslyAllowSignInWithoutUserInCatalog: true
+----
+--
+
+`callbackUrl`::
+--
+{rhsso} callback URL.
+
+.`app-config-rhdh.yaml` fragment with optional `callbackURL` field
+[source,yaml]
+----
+auth:
+ providers:
+ oidc:
+ production:
+ callbackUrl: ${AUTH_OIDC_CALLBACK_URL}
+----
+--
+
+`tokenEndpointAuthMethod`::
+--
+Token endpoint authentication method.
+
+.`app-config-rhdh.yaml` fragment with optional `tokenEndpointAuthMethod` field
+[source,yaml]
+----
+auth:
+ providers:
+ oidc:
+ production:
+ tokenEndpointAuthMethod: ${AUTH_OIDC_TOKEN_ENDPOINT_METHOD}
+----
+--
+
+`tokenSignedResponseAlg`::
+--
+Token signed response algorithm.
+
+.`app-config-rhdh.yaml` fragment with optional `tokenSignedResponseAlg` field
+[source,yaml]
+----
+auth:
+ providers:
+ oidc:
+ production:
+ tokenSignedResponseAlg: ${AUTH_OIDC_SIGNED_RESPONSE_ALG}
+----
+--
+
+`scope`::
+--
+{rhsso} scope.
+
+.`app-config-rhdh.yaml` fragment with optional `scope` field
+[source,yaml]
+----
+auth:
+ providers:
+ oidc:
+ production:
+ scope: ${AUTH_OIDC_SCOPE}
+----
+--
+
+`signIn.resolvers`::
+--
+Declarative resolvers to override the default resolver: `emailLocalPartMatchingUserEntityName`.
+The authentication provider tries each sign-in resolver until it succeeds, and fails if none succeed.
+
+.`app-config-rhdh.yaml` fragment with optional `callbackURL` field
+[source,yaml]
+----
+auth:
+ providers:
+ oidc:
+ production:
+ signIn:
+ resolvers:
+ - resolver: preferredUsernameMatchingUserEntityName
+ - resolver: emailMatchingUserEntityProfileEmail
+ - resolver: emailLocalPartMatchingUserEntityName
+----
+--
+
+--
+
+.Verification
+. Go to the {product-short} login page.
+. Your {product-short} sign-in page displays *Sign in using OIDC* and the Guest user sign-in is disabled.
+. Log in with OIDC by using the saved **Username** and **Password** values.
+
diff --git a/modules/authentication/proc-provisioning-users-from-github-to-the-software-catalog.adoc b/modules/authentication/proc-provisioning-users-from-github-to-the-software-catalog.adoc
new file mode 100644
index 0000000000..b1d001b67e
--- /dev/null
+++ b/modules/authentication/proc-provisioning-users-from-github-to-the-software-catalog.adoc
@@ -0,0 +1,76 @@
+[id="provisioning-users-from-github-to-the-software-catalog"]
+= Provisioning users from GitHub to the software catalog
+
+To authenticate users, {product} requires their presence in the software catalog.
+Consider configuring {product-short} to provision users from GitHub to the software catalog on schedule, rather than provisioning the users manually.
+
+.Prerequisites
+* You have xref:enabling-authentication-with-github[enabled authentication with GitHub], including the following secrets:
+** `GITHUB_HOST_DOMAIN`
+** `GITHUB_ORGANIZATION`
+
+.Procedure
+
+* To enable GitHub member discovery, edit your custom {product-short} ConfigMap, such as `app-config-rhdh`, and add the following lines to the `app-config-rhdh.yaml` content:
++
+--
+[id=githubProviderId]
+.`app-config.yaml` fragment with mandatory `github` fields
+[source,yaml]
+----
+dangerouslyAllowSignInWithoutUserInCatalog: false
+catalog:
+ providers:
+ github:
+ providerId:
+ organization: "${GITHUB_ORGANIZATION}"
+ schedule:
+ frequency:
+ minutes: 30
+ initialDelay:
+ seconds: 15
+ timeout:
+ minutes: 15
+ githubOrg:
+ githubUrl: "${GITHUB_HOST_DOMAIN}"
+ orgs: [ "${GITHUB_ORGANIZATION}" ]
+ schedule:
+ frequency:
+ minutes: 30
+ initialDelay:
+ seconds: 15
+ timeout:
+ minutes: 15
+----
+
+`dangerouslyAllowSignInWithoutUserInCatalog: false`::
+Allow authentication only for users present in the {product-short} software catalog.
+
+`organization`, `githubUrl`, and `orgs`::
+Use the {product-short} application information that you have created in GitHub and configured in OpenShift as secrets.
+
+`schedule.frequency`::
+To specify custom schedule frequency.
+Supports cron, ISO duration, and "human duration" as used in code.
+
+`schedule.timeout`::
+To specify custom timeout.
+Supports ISO duration and "human duration" as used in code.
+
+`schedule.initialDelay`::
+To specify custom initial delay.
+Supports ISO duration and "human duration" as used in code.
+--
+
+.Verification
+. Check the console logs to verify that the synchronization is completed.
++
+.Successful synchronization example:
+[source,json]
+----
+{"class":"GithubMultiOrgEntityProvider","level":"info","message":"Reading GitHub users and teams for org: rhdh-dast","plugin":"catalog","service":"backstage","target":"https://github.com","taskId":"GithubMultiOrgEntityProvider:production:refresh","taskInstanceId":"801b3c6c-167f-473b-b43e-e0b4b780c384","timestamp":"2024-09-09 23:55:58"}
+{"class":"GithubMultiOrgEntityProvider","level":"info","message":"Read 7 GitHub users and 2 GitHub groups in 0.4 seconds. Committing...","plugin":"catalog","service":"backstage","target":"https://github.com","taskId":"GithubMultiOrgEntityProvider:production:refresh","taskInstanceId":"801b3c6c-167f-473b-b43e-e0b4b780c384","timestamp":"2024-09-09 23:55:59"}
+----
+
+. Log in with a GitHub account.
+
diff --git a/modules/authentication/proc-provisioning-users-from-microsoft-azure-to-the-software-catalog.adoc b/modules/authentication/proc-provisioning-users-from-microsoft-azure-to-the-software-catalog.adoc
new file mode 100644
index 0000000000..501d6416a4
--- /dev/null
+++ b/modules/authentication/proc-provisioning-users-from-microsoft-azure-to-the-software-catalog.adoc
@@ -0,0 +1,291 @@
+[id="provisioning-users-from-microsoft-azure-to-the-software-catalog"]
+= Provisioning users from Microsoft Azure to the software catalog
+
+To authenticate users with Microsoft Azure, after xref:enabling-authentication-with-microsoft-azure[Enabling authentication with Microsoft Azure], provision users from Microsoft Azure to the {product-short} software catalog.
+
+.Prerequisites
+* You have xref:enabling-authentication-with-microsoft-azure[enabled authentication with Microsoft Azure].
+
+.Procedure
+* To enable Microsoft Azure member discovery, edit your custom {product-short} ConfigMap, such as `app-config-rhdh`, and add following lines to the `app-config-rhdh.yaml` content:
++
+--
+[id=microsoftGraphOrgProviderId]
+.`app-config.yaml` fragment with mandatory `microsoftGraphOrg` fields
+[source,yaml]
+----
+dangerouslyAllowSignInWithoutUserInCatalog: false
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ target: https://graph.microsoft.com/v1.0
+ tenantId: ${AUTH_AZURE_TENANT_ID}
+ clientId: ${AUTH_AZURE_CLIENT_ID}
+ clientSecret: ${AUTH_AZURE_CLIENT_SECRET}
+----
+
+`dangerouslyAllowSignInWithoutUserInCatalog: false`::
+Allow authentication only for users in the {product-short} software catalog.
+
+`target: https://graph.microsoft.com/v1.0`::
+Defines the MSGraph API endpoint the provider is connecting to.
+You might change this parameter to use a different version, such as the link:https://learn.microsoft.com/en-us/graph/api/overview?view=graph-rest-beta#call-the-beta-endpoint[beta endpoint].
+
+`tenandId`, `clientId` and `clientSecret`::
+Use the {product-short} application information you created in Microsoft Azure and configured in OpenShift as secrets.
+
+Optional: Consider adding the following optional `microsoftGraphOrg.providerId` fields:
+
+[id=authority]
+`authority: https://login.microsoftonline.com`::
+Defines the authority used.
+Change the value to use a different link:https://learn.microsoft.com/en-us/graph/deployments#app-registration-and-token-service-root-endpoints[authority], such as Azure US government.
+Default value: `https://login.microsoftonline.com`.
++
+.`app-config.yaml` fragment with optional `queryMode` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ authority: https://login.microsoftonline.com/
+----
+[id=queryMode]
+`queryMode: basic | advanced`:: By default, the Microsoft Graph API only provides the `basic` feature set for querying.
+Certain features require `advanced` querying capabilities.
+See link:https://docs.microsoft.com/en-us/graph/aad-advanced-queries[Microsoft Azure Advanced queries].
++
+.`app-config.yaml` fragment with optional `queryMode` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ queryMode: advanced
+----
+
+[id=userExpand]
+`user.expand`::
+To include the expanded resource or collection referenced by a single relationship (navigation property) in your results.
+Only one relationship can be expanded in a single request.
+See https://docs.microsoft.com/en-us/graph/query-parameters#expand-parameter[Microsoft Graph query expand parameter].
+This parameter can be combined with xref:userGroupMemberFilter[] or xref:userFilter[].
++
+.`app-config.yaml` fragment with optional `user.expand` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ user:
+ expand: manager
+----
+
+[id=userFilter]
+`user.filter`::
+To filter users.
+See link:https://docs.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0#properties[Microsoft Graph API] and link:https://docs.microsoft.com/en-us/graph/query-parameters#filter-parameter[Microsoft Graph API query filter parameters syntax].
+This parameter and xref:userGroupMemberFilter[] are mutually exclusive, only one can be specified.
++
+.`app-config.yaml` fragment with optional `user.filter` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ user:
+ filter: accountEnabled eq true and userType eq 'member'
+----
+
+[id=userLoadPhotos]
+`user.loadPhotos: true | false`::
+Load photos by default.
+Set to `false` to not load user photos.
++
+.`app-config.yaml` fragment with optional `user.loadPhotos` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ user:
+ loadPhotos: true
+----
+
+[id=userSelect]
+`user.select`::
+Define the link:https://docs.microsoft.com/en-us/graph/api/resources/schemaextension?view=graph-rest-1.0[Microsoft Graph resource types] to retrieve.
++
+.`app-config.yaml` fragment with optional `user.select` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ user:
+ select: ['id', 'displayName', 'description']
+----
+
+[id="userGroupMemberFilter"]
+`userGroupMember.filter`:::
+To use group membership to get users.
+To filter groups and fetch their members.
+This parameter and xref:userFilter[] are mutually exclusive, only one can be specified.
++
+.`app-config.yaml` fragment with optional `userGroupMember.filter` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ userGroupMember:
+ filter: "displayName eq 'Backstage Users'"
+----
+
+[id="userGroupMemberSearch"]
+`userGroupMember.search`::
+To use group membership to get users.
+To search for groups and fetch their members.
+This parameter and xref:userFilter[] are mutually exclusive, only one can be specified.
++
+.`app-config.yaml` fragment with optional `userGroupMember.search` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ userGroupMember:
+ search: '"description:One" AND ("displayName:Video" OR "displayName:Drive")'
+----
+
+[id=groupExpand]
+`group.expand`::
+Optional parameter to include the expanded resource or collection referenced by a single relationship (navigation property) in your results.
+Only one relationship can be expanded in a single request.
+See https://docs.microsoft.com/en-us/graph/query-parameters#expand-parameter
+This parameter can be combined with xref:userGroupMemberFilter[] instead of xref:userFilter[].
++
+.`app-config.yaml` fragment with optional `group.expand` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ group:
+ expand: member
+----
+
+[id=groupFilter]
+`group.filter`::
+To filter groups.
+See link:https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties[Microsoft Graph API query group syntax].
++
+.`app-config.yaml` fragment with optional `group.filter` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ group:
+ filter: securityEnabled eq false and mailEnabled eq true and groupTypes/any(c:c+eq+'Unified')
+----
+
+[id=groupSearch]
+`group.search`::
+To search for groups.
+See link:https://docs.microsoft.com/en-us/graph/search-query-parameter[Microsoft Graph API query search parameter].
++
+.`app-config.yaml` fragment with optional `group.search` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ group:
+ search: '"description:One" AND ("displayName:Video" OR "displayName:Drive")'
+----
+
+[id=groupSelect]
+`group.select`::
+To define the link:https://docs.microsoft.com/en-us/graph/api/resources/schemaextension?view=graph-rest-1.0[Microsoft Graph resource types] to retrieve.
++
+.`app-config.yaml` fragment with optional `group.select` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ group:
+ select: ['id', 'displayName', 'description']
+----
+
+`schedule.frequency`::
+To specify custom schedule frequency.
+Supports cron, ISO duration, and "human duration" as used in code.
++
+.`app-config.yaml` fragment with optional `schedule.frequency` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ schedule:
+ frequency: { hours: 1 }
+----
+
+`schedule.timeout`::
+To specify custom timeout.
+Supports ISO duration and "human duration" as used in code.
++
+.`app-config.yaml` fragment with optional `schedule.timeout` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ schedule:
+ timeout: { minutes: 50 }
+----
+
+`schedule.initialDelay`::
+To specify custom initial delay.
+Supports ISO duration and "human duration" as used in code.
++
+.`app-config.yaml` fragment with optional `schedule.initialDelay` field
+[source,yaml]
+----
+catalog:
+ providers:
+ microsoftGraphOrg:
+ providerId:
+ schedule:
+ initialDelay: { seconds: 15}
+----
+--
+
+.Verification
+. Check the console logs to verify that the synchronization is completed.
++
+.Successful synchronization example:
+[source,json]
+----
+backend:start: {"class":"MicrosoftGraphOrgEntityProvider$1","level":"info","message":"Read 1 msgraph users and 1 msgraph groups in 2.2 seconds. Committing...","plugin":"catalog","service":"backstage","taskId":"MicrosoftGraphOrgEntityProvider:default:refresh","taskInstanceId":"88a67ce1-c466-41a4-9760-825e16b946be","timestamp":"2024-06-26 12:23:42"}
+backend:start: {"class":"MicrosoftGraphOrgEntityProvider$1","level":"info","message":"Committed 1 msgraph users and 1 msgraph groups in 0.0 seconds.","plugin":"catalog","service":"backstage","taskId":"MicrosoftGraphOrgEntityProvider:default:refresh","taskInstanceId":"88a67ce1-c466-41a4-9760-825e16b946be","timestamp":"2024-06-26 12:23:42"}
+----
+
+. Log in with a Microsoft Azure account.
diff --git a/modules/authentication/proc-provisioning-users-from-rhsso-to-the-software-catalog.adoc b/modules/authentication/proc-provisioning-users-from-rhsso-to-the-software-catalog.adoc
new file mode 100644
index 0000000000..ca4c10ad08
--- /dev/null
+++ b/modules/authentication/proc-provisioning-users-from-rhsso-to-the-software-catalog.adoc
@@ -0,0 +1,153 @@
+[id="provisioning-users-from-rhsso-to-the-software-catalog"]
+= Provisioning users from {rhsso-brand-name} ({rhsso}) to the software catalog
+
+.Prerequisites
+* You xref:enabling-authentication-with-rhsso[enabled authentication with {rhsso}].
+
+.Procedure
+
+* To enable {rhsso} member discovery, edit your custom {product-short} ConfigMap, such as `app-config-rhdh`, and add the following lines to the `app-config-rhdh.yaml` content:
++
+--
+[id=keycloakOrgProviderId]
+.`app-config.yaml` fragment with mandatory `keycloakOrg` fields
+[source,yaml]
+----
+dangerouslyAllowSignInWithoutUserInCatalog: false
+catalog:
+ providers:
+ keycloakOrg:
+ default:
+ baseUrl: ${AUTH_OIDC_METADATA_URL}
+ clientId: ${AUTH_OIDC_CLIENT_ID}
+ clientSecret: ${AUTH_OIDC_CLIENT_SECRET}
+----
+
+`dangerouslyAllowSignInWithoutUserInCatalog: false`::
+ Allow authentication only for users present in the {product-short} software catalog.
+
+`baseUrl`::
+Your {rhsso} server URL, defined when xref:enabling-authentication-with-rhsso[enabling authentication with {rhsso}].
+
+`clientId`::
+Your {product-short} application client ID in {rhsso}, defined when xref:enabling-authentication-with-rhsso[enabling authentication with {rhsso}].
+
+`clientSecret`::
+Your {product-short} application client secret in {rhsso}, defined when xref:enabling-authentication-with-rhsso[enabling authentication with {rhsso}].
+
+Optional: Consider adding the following optional fields:
+
+`realm`::
+Realm to synchronize.
+Default value: `master`.
++
+.`app-config.yaml` fragment with optional `realm` field
+[source,yaml]
+----
+catalog:
+ providers:
+ keycloakOrg:
+ default:
+ realm: master
+----
+
+`loginRealm`::
+Realm used to authenticate.
+Default value: `master`.
++
+.`app-config.yaml` fragment with optional `loginRealm` field
+[source,yaml]
+----
+catalog:
+ providers:
+ keycloakOrg:
+ default:
+ loginRealm: master
+----
+
+`userQuerySize`::
+User number to query simultaneously.
+Default value: `100`.
++
+.`app-config.yaml` fragment with optional `userQuerySize` field
+[source,yaml]
+----
+catalog:
+ providers:
+ keycloakOrg:
+ default:
+ userQuerySize: 100
+----
+
+`groupQuerySize`::
+Group number to query simultaneously.
+Default value: `100`.
++
+.`app-config.yaml` fragment with optional `groupQuerySize` field
+[source,yaml]
+----
+catalog:
+ providers:
+ keycloakOrg:
+ default:
+ groupQuerySize: 100
+----
+
+`schedule.frequency`::
+To specify custom schedule frequency.
+Supports cron, ISO duration, and "human duration" as used in code.
++
+.`app-config.yaml` fragment with optional `schedule.frequency` field
+[source,yaml]
+----
+catalog:
+ providers:
+ keycloakOrg:
+ default:
+ schedule:
+ frequency: { hours: 1 }
+----
+
+`schedule.timeout`::
+To specify custom timeout.
+Supports ISO duration and "human duration" as used in code.
++
+.`app-config.yaml` fragment with optional `schedule.timeout` field
+[source,yaml]
+----
+catalog:
+ providers:
+ keycloakOrg:
+ default:
+ schedule:
+ timeout: { minutes: 50 }
+----
+
+`schedule.initialDelay`::
+To specify custom initial delay.
+Supports ISO duration and "human duration" as used in code.
++
+.`app-config.yaml` fragment with optional `schedule.initialDelay` field
+[source,yaml]
+----
+catalog:
+ providers:
+ keycloakOrg:
+ default:
+ schedule:
+ initialDelay: { seconds: 15}
+----
+--
+
+.Verification
+
+. Check the console logs to verify that the synchronization is completed.
++
+.Successful synchronization example:
+[source,json]
+----
+{"class":"KeycloakOrgEntityProvider","level":"info","message":"Read 3 Keycloak users and 2 Keycloak groups in 1.5 seconds. Committing...","plugin":"catalog","service":"backstage","taskId":"KeycloakOrgEntityProvider:default:refresh","taskInstanceId":"bf0467ff-8ac4-4702-911c-380270e44dea","timestamp":"2024-09-25 13:58:04"}
+{"class":"KeycloakOrgEntityProvider","level":"info","message":"Committed 3 Keycloak users and 2 Keycloak groups in 0.0 seconds.","plugin":"catalog","service":"backstage","taskId":"KeycloakOrgEntityProvider:default:refresh","taskInstanceId":"bf0467ff-8ac4-4702-911c-380270e44dea","timestamp":"2024-09-25 13:58:04"}
+----
+
+. Log in with an {rhsso} account.
diff --git a/modules/authorization/con-rbac-conditional-policies-rhdh.adoc b/modules/authorization/con-rbac-conditional-policies-rhdh.adoc
new file mode 100644
index 0000000000..637c36a6b7
--- /dev/null
+++ b/modules/authorization/con-rbac-conditional-policies-rhdh.adoc
@@ -0,0 +1,117 @@
+[id='con-rbac-conditional-policies-rhdh_{context}']
+= Conditional policies in {product}
+
+The permission framework in {product} provides conditions, supported by the RBAC backend plugin (`backstage-plugin-rbac-backend`). The conditions work as content filters for the {product-short} resources that are provided by the RBAC backend plugin.
+
+The RBAC backend API stores conditions assigned to roles in the database. When you request to access the frontend resources, the RBAC backend API searches for the corresponding conditions and delegates them to the appropriate plugin using its plugin ID. If you are assigned to multiple roles with different conditions, then the RBAC backend merges the conditions using the `anyOf` criteria.
+
+Conditional criteria::
++
+--
+A condition in {product-short} is a simple condition with a rule and parameters. However, a condition can also contain a parameter or an array of parameters combined by conditional criteria. The supported conditional criteria includes:
+
+* `allOf`: Ensures that all conditions within the array must be true for the combined condition to be satisfied.
+
+* `anyOf`: Ensures that at least one of the conditions within the array must be true for the combined condition to be satisfied.
+
+* `not`: Ensures that the condition within it must not be true for the combined condition to be satisfied.
+--
+
+Conditional object::
++
+--
+The plugin specifies the parameters supported for conditions. You can access the conditional object schema from the RBAC API endpoint to understand how to construct a conditional JSON object, which is then used by the RBAC backend plugin API.
+
+A conditional object contains the following parameters:
+
+.Conditional object parameters
+[cols="30%,45%,25%", frame="all", options="header"]
+|===
+|Parameter
+|Type
+|Description
+
+|`result`
+|String
+|Always has the value `CONDITIONAL`
+
+|`roleEntityRef`
+|String
+|String entity reference to the RBAC role, such as `role:default/dev`
+
+|`pluginId`
+|String
+|Corresponding plugin ID, such as `catalog`
+
+|`permissionMapping`
+|String array
+|Array permission actions, such as `['read', 'update', 'delete']`
+
+|`resourceType`
+|String
+|Resource type provided by the plugin, such as `catalog-entity`
+
+|`conditions`
+|JSON
+|Condition JSON with parameters or array parameters joined by criteria
+
+|===
+--
+
+Conditional policy aliases::
++
+--
+The RBAC backend plugin (`backstage-plugin-rbac-backend`) supports the use of aliases in conditional policy rule parameters. The conditional policy aliases are dynamically replaced with the corresponding values during policy evaluation. Each alias in conditional policy is prefixed with a `$` sign indicating its special function.
+
+The supported conditional aliases include:
+
+* `$currentUser`: This alias is replaced with the user entity reference for the user who requests access to the resource. For example, if user Tom from the default namespace requests access, `$currentUser` becomes `user:default/tom`.
++
+--
+
+.Example conditional policy object with `$currentUser` alias
+[source,json]
+----
+{
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/developer",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["delete"],
+ "conditions": {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["$currentUser"]
+ }
+ }
+}
+----
+--
+
+* `$ownerRefs`: This alias is replaced with ownership references, usually as an array that includes the user entity reference and the user's parent group entity reference. For example, for user Tom from team-a, `$ownerRefs` becomes `['user:default/tom', 'group:default/team-a']`.
++
+--
+.Example conditional policy object with `$ownerRefs` alias
+[source,json]
+----
+{
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/developer",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["delete"],
+ "conditions": {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["$ownerRefs"]
+ }
+ }
+}
+----
+--
+--
+
+
+
diff --git a/modules/authorization/con-rbac-config-permission-policies-admin.adoc b/modules/authorization/con-rbac-config-permission-policies-admin.adoc
new file mode 100644
index 0000000000..15e8f74adb
--- /dev/null
+++ b/modules/authorization/con-rbac-config-permission-policies-admin.adoc
@@ -0,0 +1,36 @@
+[id='con-rbac-config-permission-policies-admin_{context}']
+= Configuration of permission policies administrators
+
+The permission policies for users and groups in the {product-short} are managed by permission policy administrators. Only permission policy administrators can access the Role-Based Access Control REST API.
+
+The purpose of configuring policy administrators is to enable a specific, restricted number of authenticated users to access the RBAC REST API. The permission policies are defined in a `policy.csv` file, which is referenced in the `app-config-rhdh` ConfigMap. OpenShift platform administrators or cluster administrators can perform this task with access to the namespace where {product} is deployed.
+
+You can enable a permission policy administrator by configuring the `app-config.yaml` file as follows:
+
+[source,yaml]
+----
+permission:
+ enabled: true
+ rbac:
+ admin:
+ users:
+ - name: user:default/joeuser
+----
+
+The permission policy role (`role:default/rbac_admin`) is a default role in {product-short} and includes some permissions upon creation, such as creating, reading, updating, and deleting permission policies/roles, as well as reading from the catalog.
+
+If the default permissions are not adequate for your requirements, you can define a new administrator role tailored to your requirements using relevant permission policies. Alternatively, you can use the optional `superUsers` configuration value, which grants unrestricted permissions across {product-short}.
+
+You can set the `superUsers` in the `app-config.yaml` file as follows:
+
+[source,yaml]
+----
+# ...
+permission:
+ enabled: true
+ rbac:
+ admin:
+ superUsers:
+ - name: user:default/joeuser
+ # ...
+----
diff --git a/modules/authorization/con-rbac-config-permission-policies-external-file.adoc b/modules/authorization/con-rbac-config-permission-policies-external-file.adoc
new file mode 100644
index 0000000000..6ef78a60c0
--- /dev/null
+++ b/modules/authorization/con-rbac-config-permission-policies-external-file.adoc
@@ -0,0 +1,66 @@
+[id='con-rbac-config-permission-policies-external-file_{context}']
+= Configuration of permission policies defined in an external file
+
+You can configure the permission policies before starting the {product}. If permission policies are defined in an external file, then you can import the same file in the {product-short}. You must define the permission policies using the following Casbin rules format:
+
+[source,format]
+---
+`p, , , , `
+---
+
+You can define roles using the following Casbin rules format:
+
+[source,format]
+---
+`g, , `
+---
+
+[NOTE]
+====
+For information about the Casbin rules format, see https://casbin.org/docs/category/the-basics[Basics of Casbin rules].
+====
+
+The following is an example of permission policies configuration:
+
+[source,csv]
+---
+`p, role:default/guests, catalog-entity, read, allow`
+
+`p, role:default/guests, catalog.entity.create, create, allow`
+
+`g, user:default/, role:default/guests`
+
+`g, group:default/, role:default/guests`
+---
+
+If a defined permission does not contain an action associated with it, then add `use` as a policy. See the following example:
+
+[source,csv]
+---
+`p, role:default/guests, kubernetes.proxy, use, allow`
+---
+
+You can define the `policy.csv` file path in the `app-config.yaml` file:
+
+[source,yaml]
+----
+permission:
+ enabled: true
+ rbac:
+ policies-csv-file: /some/path/rbac-policy.csv
+----
+
+You can use an optional configuration value that enables reloading the CSV file without restarting the {product-short} instance.
+
+Set the value of the `policyFileReload` option in the `app-config.yaml` file:
+
+[source,yaml]
+----
+# ...
+permission:
+ enabled: true
+ rbac:
+ policies-csv-file: /some/path/rbac-policy.csv
+ policyFileReload: true
+ # ...
+----
diff --git a/modules/authorization/con-rbac-config-permission-policies.adoc b/modules/authorization/con-rbac-config-permission-policies.adoc
new file mode 100644
index 0000000000..af03c52bba
--- /dev/null
+++ b/modules/authorization/con-rbac-config-permission-policies.adoc
@@ -0,0 +1,7 @@
+[id='con-rbac-config-permission-policies_{context}']
+= Permission policies configuration
+
+There are two approaches to configure the permission policies in {product}, including:
+
+* Configuration of permission policies administrators
+* Configuration of permission policies defined in an external file
diff --git a/modules/authorization/con-rbac-overview.adoc b/modules/authorization/con-rbac-overview.adoc
new file mode 100644
index 0000000000..b050019444
--- /dev/null
+++ b/modules/authorization/con-rbac-overview.adoc
@@ -0,0 +1,6 @@
+[id='con-rbac-overview_{context}']
+= Role-Based Access Control (RBAC) in {product}
+
+Role-Based Access Control is a security paradigm that restricts access to authorized users. This feature includes defining roles with specific permissions and then assigning those roles to the users.
+
+The {product} uses RBAC to improve the permission system within the platform. The RBAC feature in {product-short} introduces an administrator role and leverages the organizational structure including teams, groups, and users by facilitating efficient access control.
diff --git a/modules/authorization/con-rbac-rest-api.adoc b/modules/authorization/con-rbac-rest-api.adoc
new file mode 100644
index 0000000000..ea956895bc
--- /dev/null
+++ b/modules/authorization/con-rbac-rest-api.adoc
@@ -0,0 +1,119 @@
+[id='con-rbac-rest-api_{context}']
+= Role-based Access Control (RBAC) REST API
+
+{product} provides RBAC REST API that you can use to manage the permissions and roles in the {product-short}. This API supports you to facilitate and automate the maintenance of {product-short} permission policies and roles.
+
+Using the RBAC REST API, you can perform the following actions:
+
+* Retrieve information about all permission policies or specific permission policies, or roles
+* Create, update, or delete a permission policy or a role
+* Retrieve permission policy information about static plugins
+
+The RBAC REST API requires the following components:
+
+Authorization::
++
+--
+
+The RBAC REST API requires Bearer token authorization for the permitted user role. For development purposes, you can access a web console in a browser. When you refresh a token request in the list of network requests, you find the token in the response JSON.
+
+`Authorization: Bearer $token`
+
+For example, on the {product-short} *Homepage*, navigate to the *Network* tab and search for the `query?term=` network call. Alternatively, you can go to the *Catalog* page and select any Catalog API network call to acquire the Bearer token.
+--
+
+HTTP methods::
++
+--
+
+The RBAC REST API supports the following HTTP methods for API requests:
+
+* `GET`: Retrieves specified information from a specified resource endpoint
+* `POST`: Creates or updates a resource
+* `PUT`: Updates a resource
+* `DELETE`: Deletes a resource
+--
+
+Base URL::
++
+--
+
+The base URL for RBAC REST API requests is `pass:c[http://SERVER:PORT/api/permission/policies]`, such as `pass:c[http://localhost:7007/api/permission/policies]`.
+
+--
+
+Endpoints::
++
+--
+
+RBAC REST API endpoints, such as `/api/permission/policies/[kind]/[namespace]/[name]` for specified `kind`, `namespace`, and `name`, are the URI that you append to the base URL to access the corresponding resource.
+
+Example request URL for `/api/permission/policies/[kind]/[namespace]/[name]` endpoint is:
+
+`pass:c[http://localhost:7007/api/permission/policies/user/default/johndoe]`
+
+[NOTE]
+====
+If at least one permission is assigned to `user:default/johndoe`, then the example request URL mentioned previously returns a result if sent in a `GET` response with a valid authorization token. However, if permission is only assigned to roles, then the example request URL does not return an output.
+====
+--
+
+Request data::
++
+--
+
+HTTP `POST` requests in the RBAC REST API may require a JSON request body with data to accompany the request.
+
+Example `POST` request URL and JSON request body data for
+`pass:c[http://localhost:7007/api/permission/policies]`:
+
+[source,json]
+----
+{
+ "entityReference": "role:default/test",
+ "permission": "catalog-entity",
+ "policy": "delete",
+ "effect": "allow"
+}
+----
+--
+
+HTTP status codes::
++
+--
+
+The RBAC REST API supports the following HTTP status codes to return as responses:
+
+* `200` OK: The request was successful.
+* `201` Created: The request resulted in a new resource being successfully created.
+* `204` No Content: The request was successful, but there is no additional content to send in the response payload.
+* `400` Bad Request: input error with the request
+* `401` Unauthorized: lacks valid authentication for the requested resource
+* `403` Forbidden: refusal to authorize request
+* `404` Not Found: could not find requested resource
+* `409` Conflict: request conflict with the current state and the target resource
+--
+
+Source::
++
+--
+Each permission policy and role created using the RBAC plugin is associated with a source to maintain data consistency within the plugin. You can manipulate permission policies and roles based on the following designated source information:
+
+* CSV file
+* Configuration file
+* REST API
+* Legacy
+
+Managing roles and permission policies originating from CSV files and REST API involves straightforward modification based on their initial source information.
+
+The Configuration file pertains to the default `role:default/rbac_admin` role provided by the RBAC plugin. The default role has limited permissions to create, read, update, and delete permission policies or roles, and to read catalog entities.
+
+[NOTE]
+====
+In case the default permissions are insufficient for your administrative requirements, you can create a custom admin role with required permission policies.
+====
+
+The legacy source applies to policies and roles defined before RBAC backend plugin version `2.1.3`, and is the least restrictive among the source location options. You must update the permissions and roles in legacy source to use either REST API or the CSV file sources.
+
+You can use the `GET` requests to query roles and policies and determine the source information, if required.
+--
diff --git a/modules/authorization/con-user-stats-rhdh.adoc b/modules/authorization/con-user-stats-rhdh.adoc
new file mode 100644
index 0000000000..68dbaca4ee
--- /dev/null
+++ b/modules/authorization/con-user-stats-rhdh.adoc
@@ -0,0 +1,8 @@
+[id='con-user-stats-rhdh_{context}']
+= User statistics in {product}
+
+In {product}, the `licensed-users-info-backend` plugin provides statistical information about the logged-in users using the Web UI or REST API endpoints.
+
+The `licensed-users-info-backend` plugin enables administrators to monitor the number of active users on {product-short}. Using this feature, organizations can compare their actual usage with the number of licenses they have purchased. Additionally, you can share the user metrics with {company-name} for transparency and accurate licensing.
+
+The `licensed-users-info-backend` plugin is enabled by default. This plugin enables a *Download User List* link at the bottom of the *Administration -> RBAC* tab.
\ No newline at end of file
diff --git a/modules/authorization/proc-download-user-stats-rhdh.adoc b/modules/authorization/proc-download-user-stats-rhdh.adoc
new file mode 100644
index 0000000000..79a783df7f
--- /dev/null
+++ b/modules/authorization/proc-download-user-stats-rhdh.adoc
@@ -0,0 +1,16 @@
+[id='proc-download-user-stats-rhdh_{context}']
+= Downloading active users list in {product}
+
+You can download the list of users in CSV format using the {product-short} web interface.
+
+.Prerequisites
+
+* RBAC plugins (`@janus-idp/backstage-plugin-rbac` and `@janus-idp/backstage-plugin-rbac-backend`) must be enabled in {product}.
+* An administrator role must be assigned.
+
+.Procedure
+
+. In {product}, navigate to *Administration* and select the *RBAC* tab.
+. At the bottom of the *RBAC* page, click *Download User List*.
+. Optional: Modify the file name in the *Save as* field and click *Save*.
+. To access the downloaded users list, go to the *Downloads* folder on your local machine and open the CSV file.
diff --git a/modules/authorization/proc-mounting-the-policy-csv-file-using-helm.adoc b/modules/authorization/proc-mounting-the-policy-csv-file-using-helm.adoc
new file mode 100644
index 0000000000..1d75250ea7
--- /dev/null
+++ b/modules/authorization/proc-mounting-the-policy-csv-file-using-helm.adoc
@@ -0,0 +1,66 @@
+[id='proc-mounting-the-policy-csv-file-using-helm_{context}']
+= Mounting `policy.csv` file to the {product-short} Helm chart
+
+When the {product} is deployed with the Helm chart, you must define the `policy.csv` file by mounting it to the {product-short} Helm chart.
+
+You can add your `policy.csv` file to the {product-short} Helm Chart by creating a `configMap` and mounting it.
+
+.Prerequisites
+
+* You are logged in to your {ocp-short} account using the {ocp-short} web console.
+* {product} is installed and deployed using Helm Chart.
++
+//For more information about installing the {product} on {ocp-short} using Helm Chart, see xref:proc-install-rhdh-ocp-helm_{context}[].
+//replace with a link to the installation guide.
+
+.Procedure
+
+. In {ocp-short}, create a ConfigMap to hold the policies as shown in the following example:
++
+--
+.Example `ConfigMap`
+[source,yaml]
+----
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: rbac-policy
+ namespace: rhdh
+data:
+ rbac-policy.csv: |
+ p, role:default/guests, catalog-entity, read, allow
+ p, role:default/guests, catalog.entity.create, create, allow
+
+ g, user:default/, role:default/guests
+----
+--
+
+. In the {product-short} Helm Chart, go to *Root Schema -> Backstage chart schema -> Backstage parameters -> Backstage container additional volume mounts*.
+. Select *Add Backstage container additional volume mounts* and add the following values:
++
+--
+* *mountPath*: `opt/app-root/src/rbac`
+* *Name*: `rbac-policy`
+--
+
+. Add the RBAC policy to the *Backstage container additional volumes* in the {product-short} Helm Chart:
++
+--
+* *name*: `rbac-policy`
+* *configMap*
+** *defaultMode*: `420`
+** *name*: `rbac-policy`
+--
+
+. Update the policy path in the `app-config.yaml` file as follows:
++
+--
+.Example `app-config.yaml` file
+[source,yaml]
+----
+permission:
+ enabled: true
+ rbac:
+ policies-csv-file: ./rbac/rbac-policy.csv
+----
+--
diff --git a/modules/authorization/proc-mounting-the-policy-csv-file-using-the-operator.adoc b/modules/authorization/proc-mounting-the-policy-csv-file-using-the-operator.adoc
new file mode 100644
index 0000000000..617d41a187
--- /dev/null
+++ b/modules/authorization/proc-mounting-the-policy-csv-file-using-the-operator.adoc
@@ -0,0 +1,84 @@
+[id='proc-mounting-the-policy-csv-file-using-the-operator_{context}']
+= Mounting `policy.csv` file using the {product-short} Operator
+
+When the {product} is deployed with the Operator, you can add your `policy.csv` file using the {product-short} Operator by creating a `ConfigMap` and mounting it through your Custom Resource (CR).
+
+.Prerequisites
+
+* You are logged in to your {ocp-short} account using the {ocp-short} web console.
+* {product} is installed and deployed using the Operator.
+* You have added a custom configuration file to {ocp-short}. For more information, see link:{LinkAdminGuide}[Adding a custom configuration file to {ocp-short}].
++
+//For more information about installing the {product} on {ocp-short} using the Operator, see xref:proc-install-rhdh-ocp-operator_{context}[].
+//replace with a link to the installation guide.
+
+.Procedure
+
+. In {ocp-short}, create a ConfigMap to hold the policies as shown in the following example:
++
+--
+.Example `ConfigMap`
+[source,yaml]
+----
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: rbac-policy
+data:
+ rbac-policy.csv: |
+ p, role:default/guests, catalog-entity, read, allow
+ p, role:default/guests, catalog.entity.create, create, allow
+
+ g, user:default/, role:default/guests
+----
+--
+
+. Update the policy path in your custom `app-config.yaml` ConfigMap as follows:
++
+--
+.Example `app-config.yaml` file
+[source,yaml]
+----
+permission:
+ enabled: true
+ rbac:
+ policies-csv-file: ./rbac-policy.csv
+----
+--
+
+. From the *Developer* perspective in the {ocp-short} web console, select the *Topology* view.
+. Click the overflow menu for the {product} instance that you want to use and select *Edit Backstage* to load the YAML view of the {product} instance.
+. In the CR, enter the name of the custom `rbac-policy` ConfigMap as the value for the `spec.application.extraFiles.configMaps` field. For example:
++
+.Example custom resource
+[source, yaml]
+----
+apiVersion: rhdh.redhat.com/v1alpha1
+kind: Backstage
+metadata:
+ name: example
+spec:
+ application:
+ appConfig:
+ mountPath: /opt/app-root/src
+ configMaps:
+ - name: app-config-rhdh
+ extraEnvs:
+ secrets:
+ - name: secrets-rhdh
+ extraFiles:
+ mountPath: /opt/app-root/src
+ configMaps:
+ - name: rbac-policy
+ replicas: 1
+ route:
+ enabled: true
+ database:
+ enableLocalDb: true
+----
+. Click *Save*.
+
+.Verification
+
+. Navigate back to the *Topology* view and wait for the {product} pod to start.
+. Click the *Open URL* icon to access the {product} platform with the updated configuration settings.
diff --git a/modules/authorization/proc-rbac-config-conditional-policy-file.adoc b/modules/authorization/proc-rbac-config-conditional-policy-file.adoc
new file mode 100644
index 0000000000..07c611bb2d
--- /dev/null
+++ b/modules/authorization/proc-rbac-config-conditional-policy-file.adoc
@@ -0,0 +1,166 @@
+[id='proc-rbac-config-conditional-policy-file_{context}']
+= Configuring conditional policies defined in an external file
+
+You can configure and manage conditional policies that are defined in an external file. To define conditional policies, you can directly edit the configuration files and pass them to {product-short}, instead of using the {product-short} web UI or API. You can configure {product-short} to use these files instead of the default files.
+
+.Prerequisites
+* You are logged in to your {ocp-short} account using the {ocp-short} web console.
+* You have defined roles and associated policies in a CSV file that serves as a basis for creating roles and permissions. Ensure that you mount the CSV file to {product-short}.
++
+For more information, see xref:ref-rbac-conditional-policy-definition_title-authorization[Conditional policies definition] and xref:con-rbac-config-permission-policies-external-file_title-authorization[Configuration of permission policies defined in an external file].
+
+.Procedure
+
+. Define conditional policies in a YAML file, which includes role references, permission mappings, and conditions.
++
+--
+The following is an example of a YAML file defining conditional policies:
+
+.Example YAML file defining conditional policies
+[source,yaml]
+----
+---
+result: CONDITIONAL
+roleEntityRef: 'role:default/test'
+pluginId: catalog
+resourceType: catalog-entity
+permissionMapping:
+ - read
+ - update
+conditions:
+ rule: IS_ENTITY_OWNER
+ resourceType: catalog-entity
+ params:
+ claims:
+ - 'group:default/team-a'
+ - 'group:default/team-b'
+---
+result: CONDITIONAL
+roleEntityRef: 'role:default/test'
+pluginId: catalog
+resourceType: catalog-entity
+permissionMapping:
+ - delete
+conditions:
+ rule: IS_ENTITY_OWNER
+ resourceType: catalog-entity
+ params:
+ claims:
+ - 'group:default/team-a'
+----
+--
+. In {ocp-short}, create a ConfigMap to hold the policies as shown in the following example:
++
+--
+.Example ConfigMap
+[source, yaml]
+----
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: rbac-conditional-policy
+ namespace: rhdh
+data:
+ rbac-policy.yaml: |
+ p, role:default/guests, catalog-entity, read, allow
+
+ result: CONDITIONAL
+ roleEntityRef: 'role:default/test'
+ pluginId: catalog
+ resourceType: catalog-entity
+ permissionMapping:
+ - read
+ - update
+ conditions:
+ rule: IS_ENTITY_OWNER
+ resourceType: catalog-entity
+ params:
+ claims:
+ - 'group:default/team-a'
+ - 'group:default/team-b'
+----
+--
+
+. Open `app-config.yaml` file and specify the path to `conditionalPoliciesFile` as shown in the following example:
++
+--
+.Example `app-config.yaml` file
+[source,yaml]
+----
+permission:
+ enabled: true
+ rbac:
+ conditionalPoliciesFile: /some/path/conditional-policies.yaml
+----
+--
+
+. To enable automatic reloading of the policy file without restarting the application, add the `policyFileReload` option and set it to `true`:
++
+--
+.Example `app-config.yaml` file
+[source,yaml]
+----
+permission:
+ enabled: true
+ rbac:
+ conditionalPoliciesFile: /some/path/conditional-policies.yaml
+ policies-csv-file: /some/path/rbac-policy.csv
+ policyFileReload: true
+----
+--
+
+. Optional: Define nested conditional policies in the YAML file as needed.
++
+--
+.Example for nested conditional policies
+[source,yaml]
+----
+{
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/developer",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["delete"],
+ "conditions": {
+ "allOf": [
+ {
+ "anyOf": [
+ {
+ "rule": "IS_ENTITY_KIND",
+ "resourceType": "catalog-entity",
+ "params": {
+ "kinds": [
+ "group"
+ ]
+ }
+ },
+ {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": [
+ "$ownerRefs"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "not": {
+ "rule": "IS_ENTITY_KIND",
+ "resourceType": "catalog-entity",
+ "params": {
+ "kinds": [
+ "api"
+ ]
+ }
+ }
+ }
+ ]
+}
+}
+----
+
+In the previous example, the `role:default/developer` is granted the condition to delete catalog entities only if they are the entity owner or if the catalog entity belongs to a group. However, this condition does not apply if the catalog entity is an API.
+--
+
diff --git a/modules/authorization/proc-rbac-send-request-rbac-rest-api.adoc b/modules/authorization/proc-rbac-send-request-rbac-rest-api.adoc
new file mode 100644
index 0000000000..2721eb99d8
--- /dev/null
+++ b/modules/authorization/proc-rbac-send-request-rbac-rest-api.adoc
@@ -0,0 +1,53 @@
+[id='proc-rbac-send-request-rbac-rest-api_{context}']
+= Sending requests with the RBAC REST API using a REST client or curl utility
+
+The RBAC REST API enables you to interact with the permission policies and roles in {product-short} without using the user interface. You can send RBAC REST API requests using any REST client or curl utility.
+
+.Prerequisites
+
+* {product} is installed and running.
+
+For more information about installing {product}, see link:{installing-on-ocp-book-url}#assembly-install-rhdh-ocp-helm[{installing-on-ocp-book-title} with the Helm chart].
+
+* You have access to the {product-short}.
+
+.Procedure
+
+. Identify a relevant API endpoint to which you want to send a request, such as `POST /api/permission/policies`. Adjust any request details according to your use case.
++
+--
+*For REST client*:
+
+* Authorization: Enter the generated token from the web console.
+* HTTP method: Set to `POST`.
+* URL: Enter the RBAC REST API base URL and endpoint such as
+`pass:c[http://localhost:7007/api/permission/policies]`.
+
+
+*For curl utility*:
+
+* `-X`: Set to `POST`
+* `-H`: Set the following header:
++
+`Content-type: application/json`
++
+`Authorization: Bearer $token`
++
+`$token` is the requested token from the web console in a browser.
+
+* URL: Enter the following RBAC REST API base URL endpoint, such as `pass:c[http://localhost:7007/api/permission/policies]`
+* `-d`: Add a request JSON body
+
+*Example requests*:
+
+`curl -X POST "http://localhost:7007/api/permission/roles" -d '{"memberReferences": ["group:default/example"], "name": "role:default/test", "metadata": { "description": "This is a test role" } }' -H "Content-Type: application/json" -H "Authorization: Bearer $token" -v`
+
+`curl -X POST "http://localhost:7007/api/permission/policies" -d '[{"entityReference":"role:default/test", "permission": "catalog-entity", "policy": "read", "effect":"allow"}]' -H "Content-Type: application/json" -H "Authorization: Bearer $token" -v`
+
+`curl -X POST "http://localhost:7007/api/permission/roles/conditions" -d '{"result": "CONDITIONAL", "roleEntityRef": "role:default/test", "pluginId": "catalog", "resourceType": "catalog-entity", "permissionMapping": ["read"], "conditions": {"rule": "IS_ENTITY_OWNER", "resourceType": "catalog-entity", "params": {"claims": ["group:default/janus-authors"]}}}' -H "Content-Type: application/json" -H "Authorization: Bearer $token" -v`
+
+--
+
+. Execute the request and review the response.
+
+
diff --git a/modules/authorization/proc-rbac-ui-create-role.adoc b/modules/authorization/proc-rbac-ui-create-role.adoc
new file mode 100644
index 0000000000..f26abb6cd2
--- /dev/null
+++ b/modules/authorization/proc-rbac-ui-create-role.adoc
@@ -0,0 +1,32 @@
+[id='proc-rbac-ui-create-role_{context}']
+= Creating a role in the {product} Web UI
+
+You can create a role in the {product} using the Web UI.
+
+.Prerequisites
+* You have an administrator role in the {product-short}.
+* You have installed the `@janus-idp/backstage-plugin-rbac` plugin in {product-short}. For more information, see link:{LinkPluginsGuide}[{NameOfPluginsGuide}].
+* You have configured the required permission policies. For more information, see xref:con-rbac-config-permission-policies_{context}[].
+
+.Procedure
+
+. Go to *Administration* at the bottom of the sidebar in the {product-short}.
++
+--
+The *RBAC* tab appears, displaying all the created roles in the {product-short}.
+--
+
+. (Optional) Click any role to view the role information on the *OVERVIEW* page.
+. Click *CREATE* to create a role.
+. Enter the name and description of the role in the given fields and click *NEXT*.
+. Add users and groups using the search field, and click *NEXT*.
+. Select *Plugin* and *Permission* from the drop-downs in the *Add permission policies* section.
+. Select or clear the *Policy* that you want to set in the *Add permission policies* section, and click *NEXT*.
+. Review the added information in the *Review and create* section.
+. Click *CREATE*.
+
+.Verification
+
+The created role appears in the list available in the *RBAC* tab.
+
+
diff --git a/modules/authorization/proc-rbac-ui-delete-role.adoc b/modules/authorization/proc-rbac-ui-delete-role.adoc
new file mode 100644
index 0000000000..48746147af
--- /dev/null
+++ b/modules/authorization/proc-rbac-ui-delete-role.adoc
@@ -0,0 +1,29 @@
+[id='proc-rbac-ui-delete-role_{context}']
+= Deleting a role in the {product} Web UI
+
+You can delete a role in the {product} using the Web UI.
+
+[NOTE]
+====
+The policies generated from a `policy.csv` or ConfigMap file cannot be edited or deleted using the {product-short} Web UI.
+====
+
+.Prerequisites
+* You have an administrator role in the {product-short}.
+* You have installed the `@janus-idp/backstage-plugin-rbac` plugin in {product-short}. For more information, see link:{LinkPluginsGuide}[{NameOfPluginsGuide}].
+* You have configured the required permission policies. For more information, see xref:con-rbac-config-permission-policies_{context}[].
+* The role that you want to delete is created in the {product-short}.
+
+.Procedure
+
+. Go to *Administration* at the bottom of the sidebar in the {product-short}.
++
+--
+The *RBAC* tab appears, displaying all the created roles in the {product-short}.
+--
+
+. (Optional) Click any role to view the role information on the *OVERVIEW* page.
+. Select the delete icon from the *Actions* column for the role that you want to delete.
++
+*Delete this role?* pop-up appears on the screen.
+. Click *DELETE*.
\ No newline at end of file
diff --git a/modules/authorization/proc-rbac-ui-edit-role.adoc b/modules/authorization/proc-rbac-ui-edit-role.adoc
new file mode 100644
index 0000000000..58387edfa2
--- /dev/null
+++ b/modules/authorization/proc-rbac-ui-edit-role.adoc
@@ -0,0 +1,31 @@
+[id='proc-rbac-ui-edit-role_{context}']
+= Editing a role in the {product} Web UI
+
+You can edit a role in the {product} using the Web UI.
+
+[NOTE]
+====
+The policies generated from a `policy.csv` or ConfigMap file cannot be edited or deleted using the {product-short} Web UI.
+====
+
+.Prerequisites
+* You have an administrator role in the {product-short}.
+* You have installed the `@janus-idp/backstage-plugin-rbac` plugin in {product-short}. For more information, see link:{LinkPluginsGuide}[{NameOfPluginsGuide}].
+* You have configured the required permission policies. For more information, see xref:con-rbac-config-permission-policies_{context}[].
+* The role that you want to edit is created in the {product-short}.
+
+.Procedure
+
+. Go to *Administration* at the bottom of the sidebar in the {product-short}.
++
+--
+The *RBAC* tab appears, displaying all the created roles in the {product-short}.
+--
+
+. (Optional) Click any role to view the role information on the *OVERVIEW* page.
+. Select the edit icon for the role that you want to edit.
+. Edit the details of the role, such as name, description, users and groups, and permission policies, and click *NEXT*.
+. Review the edited details of the role and click *SAVE*.
+
+After editing a role, you can view the edited details of a role on the *OVERVIEW* page of a role. You can also edit a role’s users and groups or permissions by using the edit icon on the respective cards on the *OVERVIEW* page.
+
diff --git a/modules/authorization/proc-rbac-ui-manage-roles.adoc b/modules/authorization/proc-rbac-ui-manage-roles.adoc
new file mode 100644
index 0000000000..09ca3d11de
--- /dev/null
+++ b/modules/authorization/proc-rbac-ui-manage-roles.adoc
@@ -0,0 +1,10 @@
+[id='proc-rbac-ui-manage-roles_{context}']
+= Managing role-based access controls (RBAC) using the {product} Web UI
+
+Administrators can use the {product-short} web interface (Web UI) to allocate specific roles and permissions to individual users or groups. Allocating roles ensures that access to resources and functionalities is regulated across the {product-short}.
+
+With the administrator role in {product-short}, you can assign permissions to users and groups, which allow users or groups to view, create, modify, and delete the roles using the {product-short} Web UI.
+
+To access the RBAC features in the Web UI, you must install and configure the `@janus-idp/backstage-plugin-rbac` plugin as a dynamic plugin. For more information about installing a dynamic plugin, see link:{LinkPluginsGuide}[{NameOfPluginsGuide}].
+
+After you install the `@janus-idp/backstage-plugin-rbac` plugin, the *Administration* option appears at the bottom of the sidebar. When you can click *Administration*, the RBAC tab appears by default, displaying all of the existing roles created in the {product-short}. In the RBAC tab, you can also view the total number of users, groups, and the total number of permission policies associated with a role. You can also edit or delete a role using the *Actions* column.
\ No newline at end of file
diff --git a/modules/authorization/ref-rbac-conditional-policy-definition.adoc b/modules/authorization/ref-rbac-conditional-policy-definition.adoc
new file mode 100644
index 0000000000..464e6486f5
--- /dev/null
+++ b/modules/authorization/ref-rbac-conditional-policy-definition.adoc
@@ -0,0 +1,347 @@
+[id='ref-rbac-conditional-policy-definition_{context}']
+= Conditional policies definition
+
+You can access API endpoints for conditional policies in {product}. For example, to retrieve the available conditional rules, which can help you define these policies, you can access the `GET [api/plugins/condition-rules]` endpoint.
+
+The `api/plugins/condition-rules` returns the condition parameters schemas, for example:
+
+[source,json]
+----
+[
+ {
+ "pluginId": "catalog",
+ "rules": [
+ {
+ "name": "HAS_ANNOTATION",
+ "description": "Allow entities with the specified annotation",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "annotation": {
+ "type": "string",
+ "description": "Name of the annotation to match on"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the annotation to match on"
+ }
+ },
+ "required": [
+ "annotation"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "HAS_LABEL",
+ "description": "Allow entities with the specified label",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "label": {
+ "type": "string",
+ "description": "Name of the label to match on"
+ }
+ },
+ "required": [
+ "label"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "HAS_METADATA",
+ "description": "Allow entities with the specified metadata subfield",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "key": {
+ "type": "string",
+ "description": "Property within the entities metadata to match on"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the given property to match on"
+ }
+ },
+ "required": [
+ "key"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "HAS_SPEC",
+ "description": "Allow entities with the specified spec subfield",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "key": {
+ "type": "string",
+ "description": "Property within the entities spec to match on"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the given property to match on"
+ }
+ },
+ "required": [
+ "key"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "IS_ENTITY_KIND",
+ "description": "Allow entities matching a specified kind",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "kinds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of kinds to match at least one of"
+ }
+ },
+ "required": [
+ "kinds"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "IS_ENTITY_OWNER",
+ "description": "Allow entities owned by a specified claim",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "claims": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of claims to match at least one on within ownedBy"
+ }
+ },
+ "required": [
+ "claims"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ }
+ ]
+ }
+ ...
+]
+----
+
+The RBAC backend API constructs a condition JSON object based on the previous condition schema.
+
+== Examples of conditional policies
+
+In {product}, you can define conditional policies with or without criteria. You can use the following examples to define the conditions based on your use case:
+
+A condition without criteria::
++
+--
+Consider a condition without criteria displaying catalogs only if user is a member of the owner group. To add this condition, you can use the catalog plugin schema `IS_ENTITY_OWNER` as follows:
+
+.Example condition without criteria
+[source,json]
+----
+{
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["group:default/team-a"]
+ }
+}
+----
+
+In the previous example, the only conditional parameter used is `claims`, which contains a list of user or group entity references.
+
+You can apply the previous example condition to the RBAC REST API by adding additional parameters as follows:
+
+[source,json]
+----
+{
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/test",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["read"],
+ "conditions": {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["group:default/team-a"]
+ }
+ }
+}
+----
+--
+
+A condition with criteria::
++
+--
+Consider a condition with criteria, which displays catalogs only if user is a member of owner group OR displays list of all catalog user groups.
+
+To add the criteria, you can add another rule as `IS_ENTITY_KIND` in the condition as follows:
+
+.Example condition with criteria
+[source,json]
+----
+{
+ "anyOf": [
+ {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["group:default/team-a"]
+ }
+ },
+ {
+ "rule": "IS_ENTITY_KIND",
+ "resourceType": "catalog-entity",
+ "params": {
+ "kinds": ["Group"]
+ }
+ }
+ ]
+}
+----
+
+[NOTE]
+====
+Running conditions in parallel during creation is not supported. Therefore, consider defining nested conditional policies based on the available criteria.
+====
+
+.Example of nested conditions
+[source,json]
+----
+{
+ "anyOf": [
+ {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["group:default/team-a"]
+ }
+ },
+ {
+ "rule": "IS_ENTITY_KIND",
+ "resourceType": "catalog-entity",
+ "params": {
+ "kinds": ["Group"]
+ }
+ }
+ ],
+ "not": {
+ "rule": "IS_ENTITY_KIND",
+ "resourceType": "catalog-entity",
+ "params": { "kinds": ["Api"] }
+ }
+}
+----
+
+You can apply the previous example condition to the RBAC REST API by adding additional parameters as follows:
+
+[source,json]
+----
+{
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/test",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["read"],
+ "conditions": {
+ "anyOf": [
+ {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["group:default/team-a"]
+ }
+ },
+ {
+ "rule": "IS_ENTITY_KIND",
+ "resourceType": "catalog-entity",
+ "params": {
+ "kinds": ["Group"]
+ }
+ }
+ ]
+ }
+}
+----
+--
+
+The following examples can be used with {product-short} plugins. These examples can help you determine how to define conditional policies:
+
+.Conditional policy defined for Keycloak plugin
+[source,json]
+----
+{
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/developer",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["update", "delete"],
+ "conditions": {
+ "not": {
+ "rule": "HAS_ANNOTATION",
+ "resourceType": "catalog-entity",
+ "params": { "annotation": "keycloak.org/realm", "value": "" }
+ }
+ }
+}
+----
+
+The previous example of Keycloak plugin prevents users in the `role:default/developer` from updating or deleting users that are ingested into the catalog from the Keycloak plugin.
+
+[NOTE]
+====
+In the previous example, the annotation `keycloak.org/realm` requires the value of ``.
+====
+
+.Conditional policy defined for Quay plugin
+[source,json]
+----
+{
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/developer",
+ "pluginId": "scaffolder",
+ "resourceType": "scaffolder-action",
+ "permissionMapping": ["use"],
+ "conditions": {
+ "not": {
+ "rule": "HAS_ACTION_ID",
+ "resourceType": "scaffolder-action",
+ "params": { "actionId": "quay:create-repository" }
+ }
+ }
+}
+----
+
+The previous example of Quay plugin prevents the role `role:default/developer` from using the Quay scaffolder action. Note that `permissionMapping` contains `use`, signifying that `scaffolder-action` resource type permission does not have a permission policy.
+
+For more information about permissions in {product}, see xref:ref-rbac-permission-policies_{context}[].
+
+
+
+
+
diff --git a/modules/authorization/ref-rbac-permission-policies.adoc b/modules/authorization/ref-rbac-permission-policies.adoc
new file mode 100644
index 0000000000..f5c4a2b5a2
--- /dev/null
+++ b/modules/authorization/ref-rbac-permission-policies.adoc
@@ -0,0 +1,220 @@
+[id='ref-rbac-permission-policies_{context}']
+= Permission policies in {product}
+
+Permission policies in {product} are a set of rules to govern access to resources or functionalities. These policies state the authorization level that is granted to users based on their roles. The permission policies are implemented to maintain security and confidentiality within a given environment.
+
+You can define the following types of permissions in {product-short}:
+
+* resource type
+* basic
+
+The distinction between the two permission types depend on whether a permission includes a defined resource type.
+
+You can define the resource type permission using either the associated resource type or the permission name as shown in the following example:
+
+.Example resource type permission definition
+[source,csv]
+----
+p, role:default/myrole, catalog.entity.read, read, allow
+g, user:default/myuser, role:default/myrole
+
+p, role:default/another-role, catalog-entity, read, allow
+g, user:default/another-user, role:default/another-role
+----
+
+You can define the basic permission in {product-short} using the permission name as shown in the following example:
+
+.Example basic permission definition
+[source,csv]
+----
+p, role:default/myrole, catalog.entity.create, create, allow
+g, user:default/myuser, role:default/myrole
+----
+
+The following permission policies are supported in the {product-short}:
+
+Catalog permissions::
+
+[cols="15%,25%,15%,45%", frame="all", options="header"]
+|===
+|Name
+|Resource type
+|Policy
+|Description
+
+|`catalog.entity.read`
+|`catalog-entity`
+|read
+|Allows user or role to read from the catalog
+
+|`catalog.entity.create`
+|
+|create
+|Allows user or role to create catalog entities, including registering an existing component in the catalog
+
+|`catalog.entity.refresh`
+|`catalog-entity`
+|update
+|Allows user or role to refresh a single or multiple entities from the catalog
+
+|`catalog.entity.delete`
+|`catalog-entity`
+|delete
+|Allows user or role to delete a single or multiple entities from the catalog
+
+|`catalog.location.read`
+|
+|read
+|Allows user or role to read a single or multiple locations from the catalog
+
+|`catalog.location.create`
+|
+|create
+|Allows user or role to create locations within the catalog
+
+|`catalog.location.delete`
+|
+|delete
+|Allows user or role to delete locations from the catalog
+|===
+
+Bulk import permissions::
+
+[cols="15%,25%,15%,45%", frame="all", options="header"]
+|===
+|Name
+|Resource type
+|Policy
+|Description
+
+|`bulk.import`
+|`bulk-import`
+|
+|Allows the user to access the bulk import endpoints, such as listing all repositories and organizations accessible by all GitHub integrations and managing the import requests.
+
+|===
+
+Scaffolder permissions::
+
+[cols="15%,25%,15%,45%", frame="all", options="header"]
+|===
+|Name
+|Resource type
+|Policy
+|Description
+
+|`scaffolder.action.execute`
+|`scaffolder-action`
+|
+|Allows the execution of an action from a template
+
+|`scaffolder.template.parameter.read`
+|`scaffolder-template`
+|read
+|Allows user or role to read a single or multiple one parameters from a template
+
+|`scaffolder.template.step.read`
+|`scaffolder-template`
+|read
+|Allows user or role to read a single or multiple steps from a template
+
+|`scaffolder.task.create`
+|
+|create
+|Allows the user or role to trigger software templates which create new scaffolder tasks
+
+|`scaffolder.task.cancel`
+|
+|
+|Allows the user or role to cancel currently running scaffolder tasks
+
+|`scaffolder.task.read`
+|
+|read
+|Allows user or role to read all scaffolder tasks and their associated events and logs
+|===
+
+RBAC permissions::
+
+[cols="15%,25%,15%,45%", frame="all", options="header"]
+|===
+|Name
+|Resource type
+|Policy
+|Description
+
+|`policy.entity.read`
+|`policy-entity`
+|read
+|Allows user or role to read permission policies and roles
+
+|`policy.entity.create`
+|`policy-entity`
+|create
+|Allows user or role to create a single or multiple permission policies and roles
+
+|`policy.entity.update`
+|`policy-entity`
+|update
+|Allows user or role to update a single or multiple permission policies and roles
+
+|`policy.entity.delete`
+|`policy-entity`
+|delete
+|Allows user or role to delete a single or multiple permission policies and roles
+|===
+
+Kubernetes permissions::
+
+[cols="15%,25%,15%,45%", frame="all", options="header"]
+|===
+|Name
+|Resource type
+|Policy
+|Description
+
+|`kubernetes.proxy`
+|
+|
+|Allows user or role to access the proxy endpoint
+|===
+
+OCM permissions::
+
+[cols="15%,25%,15%,45%", frame="all", options="header"]
+|===
+|Name
+|Resource type
+|Policy
+|Description
+
+|`ocm.entity.read`
+|
+|read
+|Allows user or role to read from the OCM plugin
+
+|`ocm.cluster.read`
+|
+|read
+|Allows user or role to read the cluster information in the OCM plugin
+|===
+
+Topology permissions::
+
+[cols="15%,25%,15%,45%", frame="all", options="header"]
+|===
+|Name
+|Resource type
+|Policy
+|Description
+
+|`topology.view.read`
+|
+|read
+|Allows user or role to view the topology plugin
+
+|`kubernetes.proxy`
+|
+|
+|Allows user or role to access the proxy endpoint, allowing them to read pod logs and events within {product-very-short}
+|===
diff --git a/modules/authorization/ref-rbac-rest-api-endpoints.adoc b/modules/authorization/ref-rbac-rest-api-endpoints.adoc
new file mode 100644
index 0000000000..1e78f2ac26
--- /dev/null
+++ b/modules/authorization/ref-rbac-rest-api-endpoints.adoc
@@ -0,0 +1,1054 @@
+[id='ref-rbac-rest-api-endpoints_{context}']
+= Supported RBAC REST API endpoints
+
+The RBAC REST API provides endpoints for managing roles, permissions, and conditional policies in the {product-short} and for retrieving information about the roles and policies.
+
+== Roles
+
+The RBAC REST API supports the following endpoints for managing roles in the {product}.
+
+[GET] /api/permission/roles::
++
+--
+Returns all roles in {product-short}.
+
+.Example response (JSON)
+[source,json]
+----
+[
+ {
+ "memberReferences": ["user:default/username"],
+ "name": "role:default/guests"
+ },
+ {
+ "memberReferences": [
+ "group:default/groupname",
+ "user:default/username"
+ ],
+ "name": "role:default/rbac_admin"
+ }
+]
+----
+--
+
+[GET] /api/permission/roles/____/____/____::
++
+--
+Returns information for a single role in {product-short}.
+
+.Example response (JSON)
+[source,json]
+----
+[
+ {
+ "memberReferences": [
+ "group:default/groupname",
+ "user:default/username"
+ ],
+ "name": "role:default/rbac_admin"
+ }
+]
+----
+--
+
+[POST] /api/permission/roles/____/____/____::
++
+--
+Creates a role in {product-short}.
+
+.Request parameters
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`body`
+|The `memberReferences`, `group`, `namespace`, and `name` the new role to be created.
+|Request body
+|Required
+|===
+
+.Example request body (JSON)
+[source,json]
+----
+{
+ "memberReferences": ["group:default/test"],
+ "name": "role:default/test_admin"
+}
+----
+
+.Example response
+[source]
+----
+201 Created
+----
+--
+
+[PUT] /api/permission/roles/____/____/____::
++
+--
+Updates `memberReferences`, `kind`, `namespace`, or `name` for a role in {product-short}.
+
+.Request parameters
+The request body contains the `oldRole` and `newRole` objects:
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`body`
+|The `memberReferences`, `group`, `namespace`, and `name` the new role to be created.
+|Request body
+|Required
+|===
+
+.Example request body (JSON)
+[source,json]
+----
+{
+ "oldRole": {
+ "memberReferences": ["group:default/test"],
+ "name": "role:default/test_admin"
+ },
+ "newRole": {
+ "memberReferences": ["group:default/test", "user:default/test2"],
+ "name": "role:default/test_admin"
+ }
+}
+----
+
+.Example response
+[source]
+----
+200 OK
+----
+--
+
+[DELETE] /api/permission/roles/____/____/____?memberReferences=::
++
+--
+Deletes the specified user or group from a role in {product-short}.
+
+.Request parameters
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`kind`
+|Kind of the entity
+|String
+|Required
+
+|`namespace`
+|Namespace of the entity
+|String
+|Required
+
+|`name`
+|Name of the entity
+|String
+|Required
+
+|`memberReferences`
+|Associated group information
+|String
+|Required
+|===
+
+.Example response
+[source]
+----
+204
+----
+--
+
+[DELETE] /api/permission/roles/____/____/____::
++
+--
+Deletes a specified role from {product-short}.
+
+.Request parameters
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`kind`
+|Kind of the entity
+|String
+|Required
+
+|`namespace`
+|Namespace of the entity
+|String
+|Required
+
+|`name`
+|Name of the entity
+|String
+|Required
+|===
+
+.Example response
+[source]
+----
+204
+----
+--
+
+== Permission policies
+
+The RBAC REST API supports the following endpoints for managing permission policies in the {product}.
+
+[GET] /api/permission/policies::
++
+--
+Returns permission policies list for all users.
+
+.Example response (JSON)
+[source,json]
+----
+[
+ {
+ "entityReference": "role:default/test",
+ "permission": "catalog-entity",
+ "policy": "read",
+ "effect": "allow",
+ "metadata": {
+ "source": "csv-file"
+ }
+ },
+ {
+ "entityReference": "role:default/test",
+ "permission": "catalog.entity.create",
+ "policy": "use",
+ "effect": "allow",
+ "metadata": {
+ "source": "csv-file"
+ }
+ },
+]
+----
+--
+
+[GET] /api/permission/policies/____/____/____::
++
+--
+Returns permission policies related to the specified entity reference.
+
+.Request parameters
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`kind`
+|Kind of the entity
+|String
+|Required
+
+|`namespace`
+|Namespace of the entity
+|String
+|Required
+
+|`name`
+|Name related to the entity
+|String
+|Required
+|===
+
+.Example response (JSON)
+[source,json]
+----
+[
+ {
+ "entityReference": "role:default/test",
+ "permission": "catalog-entity",
+ "policy": "read",
+ "effect": "allow",
+ "metadata": {
+ "source": "csv-file"
+ }
+ },
+ {
+ "entityReference": "role:default/test",
+ "permission": "catalog.entity.create",
+ "policy": "use",
+ "effect": "allow",
+ "metadata": {
+ "source": "csv-file"
+ }
+ }
+]
+----
+--
+
+[POST] /api/permission/policies::
++
+--
+Creates a permission policy for a specified entity.
+
+.Request parameters
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`entityReference`
+|Reference values of an entity including `kind`, `namespace`, and `name`
+|String
+|Required
+
+|`permission`
+|Permission from a specific plugin, resource type, or name
+|String
+|Required
+
+|`policy`
+|Policy action for the permission, such as `create`, `read`, `update`, `delete`, or `use`
+|String
+|Required
+
+|`effect`
+|Indication of allowing or not allowing the policy
+|String
+|Required
+|===
+
+.Example request body (JSON)
+[source,json]
+----
+[
+ {
+ "entityReference": "role:default/test",
+ "permission": "catalog-entity",
+ "policy": "read",
+ "effect": "allow"
+ }
+]
+----
+
+.Example response
+[source]
+----
+201 Created
+----
+--
+
+[PUT] /api/permission/policies/____/____/____::
++
+--
+Updates a permission policy for a specified entity.
+
+.Request parameters
+The request body contains the `oldPolicy` and `newPolicy` objects:
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`permission`
+|Permission from a specific plugin, resource type, or name
+|String
+|Required
+
+|`policy`
+|Policy action for the permission, such as `create`, `read`, `update`, `delete`, or `use`
+|String
+|Required
+
+|`effect`
+|Indication of allowing or not allowing the policy
+|String
+|Required
+|===
+
+.Example request body (JSON)
+[source,json]
+----
+{
+ "oldPolicy": [
+ {
+ "permission": "catalog-entity",
+ "policy": "read",
+ "effect": "allow"
+ },
+ {
+ "permission": "catalog.entity.create",
+ "policy": "create",
+ "effect": "allow"
+ }
+ ],
+ "newPolicy": [
+ {
+ "permission": "catalog-entity",
+ "policy": "read",
+ "effect": "deny"
+ },
+ {
+ "permission": "policy-entity",
+ "policy": "read",
+ "effect": "allow"
+ }
+ ]
+}
+----
+
+.Example response
+[source]
+----
+200
+----
+--
+
+[DELETE] /api/permission/policies/____/____/____?permission={value1}&policy={value2}&effect={value3}::
++
+--
+Deletes a permission policy added to the specified entity.
+
+.Request parameters
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`kind`
+|Kind of the entity
+|String
+|Required
+
+|`namespace`
+|Namespace of the entity
+|String
+|Required
+
+|`name`
+|Name related to the entity
+|String
+|Required
+
+|`permission`
+|Permission from a specific plugin, resource type, or name
+|String
+|Required
+
+|`policy`
+|Policy action for the permission, such as `create`, `read`, `update`, `delete`, or `use`
+|String
+|Required
+
+|`effect`
+|Indication of allowing or not allowing the policy
+|String
+|Required
+|===
+
+.Example response
+[source]
+----
+204 No Content
+----
+--
+
+[DELETE] /api/permission/policies/____/____/____::
++
+--
+Deletes all permission policies added to the specified entity.
+
+.Request parameters
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`kind`
+|Kind of the entity
+|String
+|Required
+
+|`namespace`
+|Namespace of the entity
+|String
+|Required
+
+|`name`
+|Name related to the entity
+|String
+|Required
+|===
+
+.Example response
+[source]
+----
+204 No Content
+----
+--
+
+[GET] /api/permission/plugins/policies::
++
+--
+Returns permission policies for all static plugins.
+
+.Example response (JSON)
+[source,json]
+----
+[
+ {
+ "pluginId": "catalog",
+ "policies": [
+ {
+ "isResourced": true,
+ "permission": "catalog-entity",
+ "policy": "read"
+ },
+ {
+ "isResourced": false,
+ "permission": "catalog.entity.create",
+ "policy": "create"
+ },
+ {
+ "isResourced": true,
+ "permission": "catalog-entity",
+ "policy": "delete"
+ },
+ {
+ "isResourced": true,
+ "permission": "catalog-entity",
+ "policy": "update"
+ },
+ {
+ "isResourced": false,
+ "permission": "catalog.location.read",
+ "policy": "read"
+ },
+ {
+ "isResourced": false,
+ "permission": "catalog.location.create",
+ "policy": "create"
+ },
+ {
+ "isResourced": false,
+ "permission": "catalog.location.delete",
+ "policy": "delete"
+ }
+ ]
+ },
+ ...
+]
+
+----
+--
+
+== Conditional policies
+
+The RBAC REST API supports the following endpoints for managing conditional policies in the {product}.
+
+[GET] /api/permission/plugins/condition-rules::
++
+--
+Returns available conditional rule parameter schemas for the available plugins that are enabled in {product-short}.
+
+.Example response (JSON)
+[source,json]
+----
+[
+ {
+ "pluginId": "catalog",
+ "rules": [
+ {
+ "name": "HAS_ANNOTATION",
+ "description": "Allow entities with the specified annotation",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "annotation": {
+ "type": "string",
+ "description": "Name of the annotation to match on"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the annotation to match on"
+ }
+ },
+ "required": [
+ "annotation"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "HAS_LABEL",
+ "description": "Allow entities with the specified label",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "label": {
+ "type": "string",
+ "description": "Name of the label to match on"
+ }
+ },
+ "required": [
+ "label"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "HAS_METADATA",
+ "description": "Allow entities with the specified metadata subfield",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "key": {
+ "type": "string",
+ "description": "Property within the entities metadata to match on"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the given property to match on"
+ }
+ },
+ "required": [
+ "key"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "HAS_SPEC",
+ "description": "Allow entities with the specified spec subfield",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "key": {
+ "type": "string",
+ "description": "Property within the entities spec to match on"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the given property to match on"
+ }
+ },
+ "required": [
+ "key"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "IS_ENTITY_KIND",
+ "description": "Allow entities matching a specified kind",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "kinds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of kinds to match at least one of"
+ }
+ },
+ "required": [
+ "kinds"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ },
+ {
+ "name": "IS_ENTITY_OWNER",
+ "description": "Allow entities owned by a specified claim",
+ "resourceType": "catalog-entity",
+ "paramsSchema": {
+ "type": "object",
+ "properties": {
+ "claims": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of claims to match at least one on within ownedBy"
+ }
+ },
+ "required": [
+ "claims"
+ ],
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ }
+ }
+ ]
+ }
+ ...
+]
+----
+--
+
+[GET] /api/permission/roles/conditions/:id::
++
+--
+Returns conditions for the specified ID.
+
+.Example response (JSON)
+[source,json]
+----
+{
+ "id": 1,
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/test",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["read"],
+ "conditions": {
+ "anyOf": [
+ {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["group:default/team-a"]
+ }
+ },
+ {
+ "rule": "IS_ENTITY_KIND",
+ "resourceType": "catalog-entity",
+ "params": {
+ "kinds": ["Group"]
+ }
+ }
+ ]
+ }
+}
+----
+--
+
+[GET] /api/permission/roles/conditions::
++
+--
+Returns list of all conditions for all roles.
+
+.Example response (JSON)
+[source,json]
+----
+[
+ {
+ "id": 1,
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/test",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["read"],
+ "conditions": {
+ "anyOf": [
+ {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["group:default/team-a"]
+ }
+ },
+ {
+ "rule": "IS_ENTITY_KIND",
+ "resourceType": "catalog-entity",
+ "params": {
+ "kinds": ["Group"]
+ }
+ }
+ ]
+ }
+ }
+]
+----
+--
+
+[POST] /api/permission/roles/conditions::
++
+--
+Creates a conditional policy for the specified role.
+
+.Request parameters
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`result`
+|Always has the value `CONDITIONAL`
+|String
+|Required
+
+|`roleEntityRef`
+|String entity reference to the RBAC role, such as `role:default/dev`
+|String
+|Required
+
+|`pluginId`
+|Corresponding plugin ID, such as `catalog`
+|String
+|Required
+
+|`permissionMapping`
+|Array permission action, such as `['read', 'update', 'delete']`
+|String array
+|Required
+
+|`resourceType`
+|Resource type provided by the plugin, such as `catalog-entity`
+|String
+|Required
+
+|`conditions`
+|Condition JSON with parameters or array parameters joined by criteria
+|JSON
+|Required
+
+|`name`
+|Name of the role
+|String
+|Required
+
+|`metadata.description`
+|The description of the role
+|String
+|Optional
+|===
+
+.Example request body (JSON)
+[source,json]
+----
+{
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/test",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["read"],
+ "conditions": {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["group:default/team-a"]
+ }
+ }
+}
+----
+
+.Example response (JSON)
+[source,json]
+----
+{
+ "id": 1
+}
+----
+--
+
+[PUT] /permission/roles/conditions/:id::
++
+--
+Updates a condition policy for a specified ID.
+
+.Request parameters
+[cols="15%,45%,15%,25%", frame="all", options="header"]
+|===
+|Name
+|Description
+|Type
+|Presence
+
+|`result`
+|Always has the value `CONDITIONAL`
+|String
+|Required
+
+|`roleEntityRef`
+|String entity reference to the RBAC role, such as `role:default/dev`
+|String
+|Required
+
+|`pluginId`
+|Corresponding plugin ID, such as `catalog`
+|String
+|Required
+
+|`permissionMapping`
+|Array permission action, such as `['read', 'update', 'delete']`
+|String array
+|Required
+
+|`resourceType`
+|Resource type provided by the plugin, such as `catalog-entity`
+|String
+|Required
+
+|`conditions`
+|Condition JSON with parameters or array parameters joined by criteria
+|JSON
+|Required
+
+|`name`
+|Name of the role
+|String
+|Required
+
+|`metadata.description`
+|The description of the role
+|String
+|Optional
+|===
+
+.Example request body (JSON)
+[source,json]
+----
+{
+ "result": "CONDITIONAL",
+ "roleEntityRef": "role:default/test",
+ "pluginId": "catalog",
+ "resourceType": "catalog-entity",
+ "permissionMapping": ["read"],
+ "conditions": {
+ "anyOf": [
+ {
+ "rule": "IS_ENTITY_OWNER",
+ "resourceType": "catalog-entity",
+ "params": {
+ "claims": ["group:default/team-a"]
+ }
+ },
+ {
+ "rule": "IS_ENTITY_KIND",
+ "resourceType": "catalog-entity",
+ "params": {
+ "kinds": ["Group"]
+ }
+ }
+ ]
+ }
+}
+----
+
+.Example response
+[source]
+----
+200
+----
+--
+
+[DELETE] /api/permission/roles/conditions/:id::
++
+--
+Deletes a conditional policy for the specified ID.
+
+.Example response
+[source]
+----
+204
+----
+--
+
+== User statistics
+
+The `licensed-users-info-backend` plugin exposes various REST API endpoints to retrieve data related to logged-in users.
+
+No additional configuration is required for the `licensed-users-info-backend` plugin. If the RBAC backend plugin is enabled, then an administrator role must be assigned to access the endpoints, as the endpoints are protected by the `policy.entity.read` permission.
+
+The base URL for user statistics endpoints is `pass:c[http://SERVER:PORT/api/licensed-users-info]`, such as `pass:c[http://localhost:7007/api/licensed-users-info]`.
+
+[GET] /users/quantity::
++
+--
+Returns the total number of logged-in users.
+
+.Example request
+[source,bash]
+----
+curl -X GET "http://localhost:7007/api/licensed-users-info/users/quantity" \
+-H "Content-Type: application/json" \
+-H "Authorization: Bearer $token"
+----
+
+.Example response
+[source,json]
+----
+{ "quantity": "2" }
+----
+--
+
+[GET] /users::
++
+--
+Returns a list of logged-in users with their details.
+
+.Example request
+[source,bash]
+----
+curl -X GET "http://localhost:7007/api/licensed-users-info/users" \
+-H "Content-Type: application/json" \
+-H "Authorization: Bearer $token"
+----
+
+.Example response
+[source,json]
+----
+[
+ {
+ "userEntityRef": "user:default/dev",
+ "lastTimeLogin": "Thu, 22 Aug 2024 16:27:41 GMT",
+ "displayName": "John Leavy",
+ "email": "dev@redhat.com"
+ }
+]
+----
+--
+
+[GET] /users::
++
+--
+Returns a list of logged-in users in CSV format.
+
+.Example request
+[source,bash]
+----
+curl -X GET "http://localhost:7007/api/licensed-users-info/users" \
+-H "Content-Type: text/csv" \
+-H "Authorization: Bearer $token"
+----
+
+.Example response
+[source,csv]
+----
+userEntityRef,displayName,email,lastTimeLogin
+user:default/dev,John Leavy,dev@redhat.com,"Thu, 22 Aug 2024 16:27:41 GMT"
+----
+--
+
+
diff --git a/modules/con-rhdh-plugins.adoc b/modules/con-rhdh-plugins.adoc
new file mode 100644
index 0000000000..829e0b401b
--- /dev/null
+++ b/modules/con-rhdh-plugins.adoc
@@ -0,0 +1,7 @@
+[id="con-rhdh-plugins"]
+
+= Plugins in {product}
+
+The {product} application offers a unified platform with various plugins. Using the plugin ecosystem within the {product-short} application, you can access any kind of development infrastructure or software development tool.
+
+The plugins in {product-short} maximize the productivity and streamline the development workflows by maintaining the consistency in the overall user experience.
\ No newline at end of file
diff --git a/modules/conscious-language.adoc b/modules/conscious-language.adoc
new file mode 100644
index 0000000000..5772b29a50
--- /dev/null
+++ b/modules/conscious-language.adoc
@@ -0,0 +1,12 @@
+////
+Conscious language note
+Add this to the preface.
+////
+[preface]
+[discrete]
+[id="making-open-source-more-inclusive"]
+= Making open source more inclusive
+Red Hat is committed to replacing problematic language in our code, documentation, and web properties.
+We are beginning with these four terms: master, slave, blacklist, and whitelist.
+Because of the enormity of this endeavor, these changes will be implemented gradually over several upcoming releases.
+For more details, see link:https://www.redhat.com/en/blog/making-open-source-more-inclusive-eradicating-problematic-language[our CTO Chris Wright's message].
diff --git a/modules/customization/proc-customize-rhdh-branding-logo.adoc b/modules/customization/proc-customize-rhdh-branding-logo.adoc
new file mode 100644
index 0000000000..3f7fff0073
--- /dev/null
+++ b/modules/customization/proc-customize-rhdh-branding-logo.adoc
@@ -0,0 +1,34 @@
+// Module included in the following assemblies:
+// assembly-customize-rhdh-theme.adoc
+//restored module as per slack thread: https://redhat-internal.slack.com/archives/C04CUSD4JSG/p1726856912238529
+
+[id="proc-customize-rhdh-branding-logo_{context}"]
+= Customizing the branding logo of your {product-short} instance
+
+You can customize the branding logo of your {product-short} instance by configuring the `branding` section the `app-config-rhdh.yaml` file, as shown in the following example:
+
+[source,yaml]
+----
+app:
+ branding:
+ fullLogo: ${BASE64_EMBEDDED_FULL_LOGO} <1>
+ iconLogo: ${BASE64_EMBEDDED_ICON_LOGO} <2>
+----
+
+where:
+
+<1> `fullLogo` is the logo on the expanded (pinned) sidebar and expects a base64 encoded image.
+<2> `iconLogo` is the logo on the collapsed (unpinned) sidebar and expects a base64 encoded image.
+
+You can also customize the width of the branding logo by setting a value for the `fullLogoWidth` field in the `branding` section, as shown in the following example:
+
+[source,yaml]
+----
+app:
+ branding:
+ fullLogoWidth: 110px <1>
+# ...
+----
+
+<1> The default value for the logo width is `110px`. The following units are supported: `integer`, `px`, `em`, `rem`, percentage.
+
diff --git a/modules/customization/proc-customize-rhdh-font.adoc b/modules/customization/proc-customize-rhdh-font.adoc
new file mode 100644
index 0000000000..9ba0c69e82
--- /dev/null
+++ b/modules/customization/proc-customize-rhdh-font.adoc
@@ -0,0 +1,59 @@
+// Module included in the following assemblies:
+// assembly-customize-rhdh-theme.adoc
+
+[id="proc-customize-rhdh-font_{context}"]
+= Customizing the font for your {product-short} instance
+
+You can configure the `typography` section of the `app-config-rhdh.yaml` file to change the default font family and size of the page text, as well as the font family and size of each heading level, as shown in the following example:
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light:
+ typography:
+ fontFamily: "Times New Roman"
+ htmlFontSize: 11 # smaller is bigger
+ h1:
+ fontFamily: "Times New Roman"
+ fontSize: 40
+ h2:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+ h3:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+ h4:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+ h5:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+ h6:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+ dark:
+ typography:
+ fontFamily: "Times New Roman"
+ htmlFontSize: 11 # smaller is bigger
+ h1:
+ fontFamily: "Times New Roman"
+ fontSize: 40
+ h2:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+ h3:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+ h4:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+ h5:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+ h6:
+ fontFamily: "Times New Roman"
+ fontSize: 30
+# ...
+----
diff --git a/modules/customization/proc-customize-rhdh-page-theme.adoc b/modules/customization/proc-customize-rhdh-page-theme.adoc
new file mode 100644
index 0000000000..45e17866d5
--- /dev/null
+++ b/modules/customization/proc-customize-rhdh-page-theme.adoc
@@ -0,0 +1,43 @@
+// Module included in the following assemblies:
+// assembly-customize-rhdh-theme.adoc
+
+[id="proc-customize-rhdh-page-theme_{context}"]
+= Customizing the page theme header for your {product-short} instance
+
+You can customize the header color for the light and dark theme modes in your {product-short} instance by modifying the `branding.theme` section of the `app-config-rhdh.yaml` file. You can also customize the page headers for additional {product-short} pages, such as the *Home*, *Catalog*, and *APIs* pages.
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light: <1>
+ palette: {}
+ pageTheme:
+ default: <2>
+ backgroundColor: "" <3>
+ fontColor: "" <4>
+ shape: none <5>
+ apis: <6>
+ backgroundColor: ""
+ fontColor: ""
+ shape: none
+ dark:
+ palette: {}
+ pageTheme:
+ default:
+ backgroundColor: ""
+ fontColor: ""
+ shape: none
+# ...
+----
+
+<1> The theme mode, for example, `light` or `dark`
+<2> The `yaml` header for the default page theme configuration
+<3> The color of the page header background, for example, `#ffffff` or `white`
+<4> The color of the text in the page header, for example, `#000000` or `black`
+<5> The pattern on the page header, for example, `wave`, `round`, or `none`
+<6> The `yaml` header for a specific page theme configuration, for example, `apis`, `home`
+
+//The page theme name depends on the plugin that you are customizing the page header for.
+//can include information about this topic in the future.
diff --git a/modules/customization/proc-customize-rhdh-palette.adoc b/modules/customization/proc-customize-rhdh-palette.adoc
new file mode 100644
index 0000000000..20f3b418d7
--- /dev/null
+++ b/modules/customization/proc-customize-rhdh-palette.adoc
@@ -0,0 +1,43 @@
+// Module included in the following assemblies:
+// assembly-customize-rhdh-theme.adoc
+
+[id="proc-customize-rhdh-branding_{context}"]
+= Customizing the theme mode color palettes for your {product-short} instance
+
+You can customize the color palettes of the light and dark theme modes in your {product-short} instance by configuring the `light.palette` and `dark.palette` parameters in the `branding.theme` section of the `app-config-rhdh.yaml` file, as shown in the following example:
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light:
+ palette:
+ primary:
+ main: <1>
+ navigation:
+ indicator: <2>
+ pageTheme:
+ default:
+ backgroundColor: [, ] <3>
+ dark:
+ palette:
+ primary:
+ main: <4>
+ navigation:
+ indicator: <5>
+ pageTheme:
+ default:
+ backgroundColor: [, ] <6>
+# ...
+----
+
+<1> The main primary color for the light color palette, for example, `#ffffff` or `white`
+<2> The color of the navigation indicator for the light color palette, which is a vertical bar that indicates the selected tab in the navigation panel, for example, `#FF0000` or `red`
+<3> The background color for the default page theme for the light color palette, for example, `#ffffff` or `white`
+<4> The main primary color for the dark color palette, for example, `#000000` or `black`
+<5> The color of the navigation indicator for the dark color palette, which is a vertical bar that indicates the selected tab in the navigation panel, for example, `#FF0000` or `red`
+<6> The background color for the default page theme for the dark color palette, for example, `#000000` or `black`
+
+.Additional resources
+* xref:proc-customizing-rhdh-theme-mode_{context}[]
diff --git a/modules/customization/proc-customize-rhdh-sidebar-logo.adoc b/modules/customization/proc-customize-rhdh-sidebar-logo.adoc
new file mode 100644
index 0000000000..55fc38a9f0
--- /dev/null
+++ b/modules/customization/proc-customize-rhdh-sidebar-logo.adoc
@@ -0,0 +1,17 @@
+// Module included in the following assemblies:
+// None
+//Archived since the section has been merged with proc-customize-rhdh-branding-logo.adoc in PR #514
+
+[id="proc-customize-rhdh-sidebar-logo_{context}"]
+= Customizing the sidebar logo width for your {product-short} instance
+You can customize the width of the sidebar logo by setting a value for the `fullLogoWidth` field in the `branding` section of the `app-config-rhdh.yaml` file, as shown in the following example:
+
+[source,yaml]
+----
+app:
+ branding:
+ fullLogoWidth: 110px
+# ...
+----
+
+The default value for the logo width is 110px. The following units are supported: integer, `px`, `em`, `rem`, percentage.
diff --git a/modules/customization/proc-customize-rhdh-sidebar-menuitems.adoc b/modules/customization/proc-customize-rhdh-sidebar-menuitems.adoc
new file mode 100644
index 0000000000..61895a6456
--- /dev/null
+++ b/modules/customization/proc-customize-rhdh-sidebar-menuitems.adoc
@@ -0,0 +1,128 @@
+[id='proc-customize-rhdh-sidebar-menuitems_{context}']
+= Customizing the sidebar menu items for your {product-short} instance
+
+The sidebar menu in {product} consists of two main parts:
+
+* *Main menu items*: These items are the static menu items that form the core navigation structure of sidebar. These menu items remain consistent and are predefined.
+
+* *Dynamic plugin menu items*: These items are displayed beneath the main menu and can be customized based on the plugins installed. The main menu items section is dynamic and can change based on your preferences and installed plugins.
+
+.Procedure
+
+. Customize the main menu items using the following steps:
++
+--
+.. Open the `app-config-rhdh.yaml` file.
+.. To customize the order and parent-child relationships for the main menu items, use the `dynamicPlugins.frontend.default.main-menu-items.menuItems` field.
+.. For dynamic plugin menu items, use the `dynamicPlugins.frontend..menuItems` field.
+
+.Example `app-config-rhdh.yaml` file
+[source,yaml]
+----
+dynamicPlugins:
+ frontend:
+ : # same as `scalprum.name` key in plugin's `package.json`
+ menuItems: # optional, allows you to configure plugin menu items in the main sidebar navigation
+ : # unique name in the plugin menu items list <1>
+ icon: home | group | category | extension | school | __ # <2>
+ title: My Plugin Page # optional, same as `menuItem.text` in `dynamicRoutes` <3>
+ priority: 10 # optional, defines the order of menu items in the sidebar <4>
+ parent: favorites # optional, defines parent-child relationships for nested menu items <5>
+----
+
+You can modify the fields in the previous example to configure the desired order and parent-child relationships of the sidebar menu items.
+
+<1> This attribute represents a unique name in the main sidebar navigation. It can denote either a standalone menu item or a parent menu item. If this attribute represents a plugin menu item, the name of the attribute must match with the corresponding path in `dynamicRoutes`. For example, if `dynamicRoutes` defines `path: /my-plugin`, then `menu_item_name` must be defined as `my-plugin`.
++
+For more complex, multi-segment paths such as `path: /metrics/users/info`, the `menu_item_name` must use dot notation to represent the full path, for example, `metrics.users.info`. Trailing and leading slashes in paths are ignored. For example, `path: /docs` results in `menu_item_name: docs`, and `path: /metrics/users` results in `menu_item_name: metrics.users`.
+
+<2> This optional attribute specifies the icon for the menu item. You can use default icons or extend the icon set with dynamic plugins. {product-short} also provides additional icons in its internal library, such as:
++
+.Home Icon in the internal library
+[source, yaml]
+----
+dynamicPlugins:
+ frontend:
+ :
+ menuItems:
+ :
+ icon: home
+----
++
+Similarly, the internal library includes icons for `group`, `category`, `extension`, and `school`. If the icon is already defined in the `dynamicRoutes` configuration under `menuItem.icon`, it can be removed from the in the `menuItems` configuration. Also, both SVG and HTML image icons are supported. For example:
++
+.Example SVG icon
+[source,html]
+----
+icon:
+----
++
+.Example image icon
+[source,html]
+----
+icon: https://img.icons8.com/ios-glyphs/20/FFFFFF/shop.png
+----
+
+<3> This optional attribute specifies the title of the menu item. It can be removed if the title is already specified in the `dynamicRoutes` configuration under `menuItem.text`.
+
+<4> This optional attribute sets the order in which menu items appear in the sidebar. The default priority is 0, which places the item at the bottom of the list. A higher priority value places the item higher in the sidebar. You can define this attribute for each section.
+
+<5> This optional attribute specifies the parent menu item under which the current item is nested. If this attribute is used, the parent menu item must be defined elsewhere in the `menuItems` configuration of any enabled plugin. You can define this attribute for each section.
+
+.Example `menuItems` configuration
+[source,yaml]
+----
+dynamicPlugins:
+ frontend:
+ :
+ dynamicRoutes:
+ - path: /my-plugin
+ module: CustomModule
+ importName: FooPluginPage
+ menuItem:
+ icon: fooIcon
+ text: Foo Plugin Page
+ menuItems:
+ my-plugin: # matches `path` in `dynamicRoutes`
+ priority: 10 # controls order of plugins under the parent menu item
+ parent: favorites # nests this plugin under the `favorites` parent menu item
+ favorites: # configuration for the parent menu item
+ icon: favorite # icon from RHDH system icons
+ title: Favorites # title for the parent menu item
+ priority: 100 # controls the order of this top-level menu item
+----
+--
+
+. To ensure that a menu item is identified as a main menu item, you must add `default.` prefix to its key. For example:
++
+--
+.Example configuration of main menu items in sidebar navigation
+[source,yaml]
+----
+dynamicPlugins:
+ frontend:
+ default.main-menu-items: # key for configuring static main menu items
+ default.: # key of the menu item configuration. `default.` prefix is required for a main menu item key <1>
+ parent: my_menu_group # optional, specifies the parent menu item for this item
+ priority: 10 # optional, specifies the order of this menu item within its menu level
+ default.: # must be configured if it is specified as the parent of any menu items. `default.` prefix is required for a main menu item key
+ icon: my_menu_group_icon # required for parent menu items, defines the icon for the menu group
+ title: my_menu_group_title # required for parent menu items, defines the icon for the menu group
+ priority: 100 # optional, specifies the order of the parent menu item in the sidebar
+----
+
+
+<1> The `default.` prefix identifes an item as a main menu item. You can add the `default.` prefix to both individual menu items or parent menu group configuration, such as `default.` in the previous example.
+
+[NOTE]
+====
+The default priority of main menu items determines their order in the sidebar. You can customize the order of the static main menu items by adjusting their priority values. Ensure that the priority and title of each item is clear to facilitate easy reordering.
+====
+--
+
+
+
+
+
+
+
diff --git a/modules/customization/proc-customize-rhdh-tab-tooltip.adoc b/modules/customization/proc-customize-rhdh-tab-tooltip.adoc
new file mode 100644
index 0000000000..66de517a91
--- /dev/null
+++ b/modules/customization/proc-customize-rhdh-tab-tooltip.adoc
@@ -0,0 +1,14 @@
+// Module included in the following assemblies:
+// assembly-customize-rhdh-theme.adoc
+
+[id="proc-customizing-rhdh-tab-tooltip_{context}"]
+= Customizing the application title for your {product-short} instance
+
+You can customize the app title text by setting a value for the `title` field, as shown in the following example:
+
+[source,yaml]
+----
+app:
+ title: My custom developer hub
+# ...
+----
diff --git a/modules/customization/proc-customize-rhdh-theme-mode.adoc b/modules/customization/proc-customize-rhdh-theme-mode.adoc
new file mode 100644
index 0000000000..72c638017c
--- /dev/null
+++ b/modules/customization/proc-customize-rhdh-theme-mode.adoc
@@ -0,0 +1,34 @@
+// Module included in the following assemblies:
+// assembly-customize-rhdh-theme.adoc
+
+[id="proc-customizing-rhdh-theme-mode_{context}"]
+= Customizing the theme mode for your {product-short} instance
+
+[NOTE]
+====
+In {product-short}, theme configurations are used to change the look and feel of different UI components. So, you might notice changes in different UI components, such as buttons, tabs, sidebars, cards, and tables along with some changes in background color and font used on the {product-very-short} pages.
+====
+
+You can choose one of the following theme modes for your {product-short} instance:
+
+* Light theme
+* Dark theme
+* Auto
+
+The default theme mode is Auto, which automatically sets the light or dark theme based on your system preferences.
+
+.Prerequisites
+
+* You are logged in to the {product-short} web console.
+
+.Procedure
+
+. From the {product-short} web console, click *Settings*.
+. From the *Appearance* panel, click *LIGHT THEME*, *DARK THEME*, or *AUTO* to change the theme mode.
++
+image::user-guide/custom-theme-mode-1.png[]
+
+// [NOTE]
+// ====
+// If you choose the *AUTO* theme mode, ...
+// ====
diff --git a/modules/customization/ref-customize-rhdh-custom-components.adoc b/modules/customization/ref-customize-rhdh-custom-components.adoc
new file mode 100644
index 0000000000..d7305ff86f
--- /dev/null
+++ b/modules/customization/ref-customize-rhdh-custom-components.adoc
@@ -0,0 +1,51 @@
+// Module included in the following assemblies:
+// assembly-customize-rhdh-theme.adoc
+
+[id="ref-customize-rhdh-custom-components_{context}"]
+= Custom component options for your {product-short} instance
+
+There are two component variants that you can use to customize various components of your {product-short} theme:
+
+* *Patternfly*
+* *MUI*
+
+In addition to assigning a component variant to each parameter in the light or dark theme mode configurations, you can toggle the `rippleEffect` `on` or `off`.
+
+The following code shows the options that you can use in the `app-config-rhdh.yaml` file to configure the theme components for your {product-short} instance:
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light:
+ options:
+ rippleEffect: off / on
+ paper: patternfly / mui
+ buttons: patternfly / mui
+ inputs: patternfly / mui
+ accordions: patternfly / mui
+ sidebars: patternfly / mui
+ pages: patternfly / mui
+ headers: patternfly / mui
+ toolbars: patternfly / mui
+ dialogs: patternfly / mui
+ cards: patternfly / mui
+ tables: patternfly / mui
+ tabs: patternfly / mui
+ dark:
+ options:
+ rippleEffect: off / on
+ paper: patternfly / mui
+ buttons: patternfly / mui
+ inputs: patternfly / mui
+ accordions: patternfly / mui
+ sidebars: patternfly / mui
+ pages: patternfly / mui
+ headers: patternfly / mui
+ toolbars: patternfly / mui
+ dialogs: patternfly / mui
+ cards: patternfly / mui
+ tables: patternfly / mui
+ tabs: patternfly / mui
+----
diff --git a/modules/customization/ref-customize-rhdh-default-backstage.adoc b/modules/customization/ref-customize-rhdh-default-backstage.adoc
new file mode 100644
index 0000000000..ecd6a48205
--- /dev/null
+++ b/modules/customization/ref-customize-rhdh-default-backstage.adoc
@@ -0,0 +1,254 @@
+// Module included in the following assemblies:
+// assembly-customize-rhdh-theme.adoc
+
+[id="ref-customize-rhdh-default-backstage_{context}"]
+= Default Backstage theme
+
+You can use the default Backstage theme configurations to make your {product-short} instance look like a standard Backstage instance. You can also modify the `app-config-rhdh.yaml` file to customize or disable particular parameters.
+
+== Default Backstage theme color palette
+
+The `app-config-rhdh.yaml` file uses the following configurations for the default Backstage color palette:
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light:
+ variant: "backstage"
+ mode: "light"
+ palette:
+ background:
+ default: "#F8F8F8"
+ paper: "#FFFFFF"
+ banner:
+ closeButtonColor: "#FFFFFF"
+ error: "#E22134"
+ info: "#2E77D0"
+ link: "#000000"
+ text: "#FFFFFF"
+ warning: "#FF9800"
+ border: "#E6E6E6"
+ bursts:
+ backgroundColor:
+ default: "#7C3699"
+ fontColor: "#FEFEFE"
+ gradient:
+ linear: "linear-gradient(-137deg, #4BB8A5 0%, #187656 100%)"
+ slackChannelText: "#ddd"
+ errorBackground: "#FFEBEE"
+ errorText: "#CA001B"
+ gold: "#FFD600"
+ highlight: "#FFFBCC"
+ infoBackground: "#ebf5ff"
+ infoText: "#004e8a"
+ link: "#0A6EBE"
+ linkHover: "#2196F3"
+ navigation:
+ background: "#171717"
+ color: "#b5b5b5"
+ indicator: "#9BF0E1"
+ navItem:
+ hoverBackground: "#404040"
+ selectedColor: "#FFF"
+ submenu:
+ background: "#404040"
+ pinSidebarButton:
+ background: "#BDBDBD"
+ icon: "#181818"
+ primary:
+ main: "#1F5493"
+ status:
+ aborted: "#757575"
+ error: "#E22134"
+ ok: "#1DB954"
+ pending: "#FFED51"
+ running: "#1F5493"
+ warning: "#FF9800"
+ tabbar:
+ indicator: "#9BF0E1"
+ textContrast: "#000000"
+ textSubtle: "#6E6E6E"
+ textVerySubtle: "#DDD"
+ warningBackground: "#F59B23"
+ warningText: "#000000"
+
+ dark:
+ variant: "backstage"
+ mode: "dark"
+ palette:
+ background:
+ default: "#333333"
+ paper: "#424242"
+ banner:
+ closeButtonColor: "#FFFFFF"
+ error: "#E22134"
+ info: "#2E77D0"
+ link: "#000000"
+ text: "#FFFFFF"
+ warning: "#FF9800"
+ border: "#E6E6E6"
+ bursts:
+ backgroundColor:
+ default: "#7C3699"
+ fontColor: "#FEFEFE"
+ gradient:
+ linear: "linear-gradient(-137deg, #4BB8A5 0%, #187656 100%)"
+ slackChannelText: "#ddd"
+ errorBackground: "#FFEBEE"
+ errorText: "#CA001B"
+ gold: "#FFD600"
+ highlight: "#FFFBCC"
+ infoBackground: "#ebf5ff"
+ infoText: "#004e8a"
+ link: "#9CC9FF"
+ linkHover: "#82BAFD"
+ mode: "dark"
+ navigation:
+ background: "#424242"
+ color: "#b5b5b5"
+ indicator: "#9BF0E1"
+ navItem:
+ hoverBackground: "#404040"
+ selectedColor: "#FFF"
+ submenu:
+ background: "#404040"
+ pinSidebarButton:
+ background: "#BDBDBD"
+ icon: "#404040"
+ primary:
+ dark: "#82BAFD"
+ main: "#9CC9FF"
+ secondary:
+ main: "#FF88B2"
+ status:
+ aborted: "#9E9E9E"
+ error: "#F84C55"
+ ok: "#71CF88"
+ pending: "#FEF071"
+ running: "#3488E3"
+ warning: "#FFB84D"
+ tabbar:
+ indicator: "#9BF0E1"
+ textContrast: "#FFFFFF"
+ textSubtle: "#CCCCCC"
+ textVerySubtle: "#727272"
+ warningBackground: "#F59B23"
+ warningText: "#000000"
+----
+
+Alternatively, you can use the following `variant` and `mode` values in the `app-config-rhdh.yaml` file to apply the previous default configuration:
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light:
+ variant: "backstage"
+ mode: "light"
+ dark:
+ variant: "backstage"
+ mode: "dark"
+----
+
+== Default Backstage page themes
+
+The default Backstage header color is white in light mode and black in dark mode, as shown in the following `app-config-rhdh.yaml` file configuration:
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light:
+ palette: {}
+ defaultPageTheme: default
+ pageTheme:
+ default:
+ backgroundColor: ['#005B4B'] # teal
+ fontColor: '#ffffff'
+ shape: wave
+ documentation:
+ backgroundColor: ['#C8077A', '#C2297D'] # pinkSea
+ fontColor: '#ffffff'
+ shape: wave2
+ tool:
+ backgroundColor: ['#8912CA', '#3E00EA'] # purpleSky
+ fontColor: '#ffffff'
+ shape: round
+ service:
+ backgroundColor: ['#006D8F', '#0049A1'] # marineBlue
+ fontColor: '#ffffff'
+ shape: wave
+ website:
+ backgroundColor: ['#0027AF', '#270094'] # veryBlue
+ fontColor: '#ffffff'
+ shape: wave
+ library:
+ backgroundColor: ['#98002B', '#8D1134'] # rubyRed
+ fontColor: '#ffffff'
+ shape: wave
+ other:
+ backgroundColor: ['#171717', '#383838'] # darkGrey
+ fontColor: '#ffffff'
+ shape: wave
+ app:
+ backgroundColor: ['#BE2200', '#A41D00'] # toastyOrange
+ fontColor: '#ffffff'
+ shape: shapes.wave
+ apis:
+ backgroundColor: ['#005B4B'] # teal
+ fontColor: '#ffffff'
+ shape: wave2
+ card:
+ backgroundColor: ['#4BB8A5', '#187656'] # greens
+ fontColor: '#ffffff'
+ shape: wave
+
+ dark:
+ palette: {}
+ defaultPageTheme: default
+ pageTheme:
+ default:
+ backgroundColor: ['#005B4B'] # teal
+ fontColor: '#ffffff'
+ shape: wave
+ documentation:
+ backgroundColor: ['#C8077A', '#C2297D'] # pinkSea
+ fontColor: '#ffffff'
+ shape: wave2
+ tool:
+ backgroundColor: ['#8912CA', '#3E00EA'] # purpleSky
+ fontColor: '#ffffff'
+ shape: round
+ service:
+ backgroundColor: ['#006D8F', '#0049A1'] # marineBlue
+ fontColor: '#ffffff'
+ shape: wave
+ website:
+ backgroundColor: ['#0027AF', '#270094'] # veryBlue
+ fontColor: '#ffffff'
+ shape: wave
+ library:
+ backgroundColor: ['#98002B', '#8D1134'] # rubyRed
+ fontColor: '#ffffff'
+ shape: wave
+ other:
+ backgroundColor: ['#171717', '#383838'] # darkGrey
+ fontColor: '#ffffff'
+ shape: wave
+ app:
+ backgroundColor: ['#BE2200', '#A41D00'] # toastyOrange
+ fontColor: '#ffffff'
+ shape: shapes.wave
+ apis:
+ backgroundColor: ['#005B4B'] # teal
+ fontColor: '#ffffff'
+ shape: wave2
+ card:
+ backgroundColor: ['#4BB8A5', '#187656'] # greens
+ fontColor: '#ffffff'
+ shape: wave
+----
diff --git a/modules/customization/ref-customize-rhdh-default-rhdh.adoc b/modules/customization/ref-customize-rhdh-default-rhdh.adoc
new file mode 100644
index 0000000000..df5d7029d3
--- /dev/null
+++ b/modules/customization/ref-customize-rhdh-default-rhdh.adoc
@@ -0,0 +1,241 @@
+// Module included in the following assemblies:
+// assembly-customize-rhdh-theme.adoc
+
+[id="ref-customize-rhdh-default-rhdh_{context}"]
+= Default {product} theme
+
+You can use the default {product} theme configurations to make your {product-short} instance look like a standard {product} instance. You can also modify the `app-config-rhdh.yaml` file to customize or disable particular parameters.
+
+== Default {product} theme color palette
+
+The `app-config-rhdh.yaml` file uses the following configurations for the default {product} color palette:
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light:
+ variant: "rhdh"
+ mode: "light"
+ palette:
+ background:
+ default: "#F8F8F8"
+ paper: "#FFFFFF"
+ banner:
+ closeButtonColor: "#FFFFFF"
+ error: "#E22134"
+ info: "#2E77D0"
+ link: "#000000"
+ text: "#FFFFFF"
+ warning: "#FF9800"
+ border: "#E6E6E6"
+ bursts:
+ backgroundColor:
+ default: "#7C3699"
+ fontColor: "#FEFEFE"
+ gradient:
+ linear: "linear-gradient(-137deg, #4BB8A5 0%, #187656 100%)"
+ slackChannelText: "#ddd"
+ errorBackground: "#FFEBEE"
+ errorText: "#CA001B"
+ gold: "#FFD600"
+ highlight: "#FFFBCC"
+ infoBackground: "#ebf5ff"
+ infoText: "#004e8a"
+ link: "#0A6EBE"
+ linkHover: "#2196F3"
+ mode: "light"
+ navigation:
+ background: "#222427"
+ indicator: "#0066CC"
+ color: "#ffffff"
+ selectedColor: "#ffffff"
+ navItem:
+ hoverBackground: "#3c3f42"
+ submenu:
+ background: "#222427"
+ pinSidebarButton:
+ background: "#BDBDBD"
+ icon: "#181818"
+ primary:
+ main: "#0066CC"
+ secondary:
+ main: "#8476D1"
+ status:
+ aborted: "#757575"
+ error: "#E22134"
+ ok: "#1DB954"
+ pending: "#FFED51"
+ running: "#1F5493"
+ warning: "#FF9800"
+ tabbar:
+ indicator: "#9BF0E1"
+ textContrast: "#000000"
+ textSubtle: "#6E6E6E"
+ textVerySubtle: "#DDD"
+ warningBackground: "#F59B23"
+ warningText: "#000000"
+ text:
+ primary: "#151515"
+ secondary: "#757575"
+ rhdh:
+ general:
+ disabledBackground: "#D2D2D2"
+ disabled: "#6A6E73"
+ searchBarBorderColor: "#E4E4E4"
+ formControlBackgroundColor: "#FFF"
+ mainSectionBackgroundColor: "#FFF"
+ headerBottomBorderColor: "#C7C7C7"
+ cardBackgroundColor: "#FFF"
+ sideBarBackgroundColor: "#212427"
+ cardBorderColor: "#C7C7C7"
+ tableTitleColor: "#181818"
+ tableSubtitleColor: "#616161"
+ tableColumnTitleColor: "#151515"
+ tableRowHover: "#F5F5F5"
+ tableBorderColor: "#E0E0E0"
+ tableBackgroundColor: "#FFF"
+ tabsBottomBorderColor: "#D2D2D2"
+ contrastText: "#FFF"
+ primary:
+ main: "#0066CC"
+ focusVisibleBorder: "#0066CC"
+ secondary:
+ main: "#8476D1"
+ focusVisibleBorder: "#8476D1"
+ cards:
+ headerTextColor: "#151515"
+ headerBackgroundColor: "#FFF"
+ headerBackgroundImage: "none"
+
+ dark:
+ variant: "rhdh"
+ mode: "dark"
+ palette:
+ background:
+ default: "#333333"
+ paper: "#424242"
+ banner:
+ closeButtonColor: "#FFFFFF"
+ error: "#E22134"
+ info: "#2E77D0"
+ link: "#000000"
+ text: "#FFFFFF"
+ warning: "#FF9800"
+ border: "#E6E6E6"
+ bursts:
+ backgroundColor:
+ default: "#7C3699"
+ fontColor: "#FEFEFE"
+ gradient:
+ linear: "linear-gradient(-137deg, #4BB8A5 0%, #187656 100%)"
+ slackChannelText: "#ddd"
+ errorBackground: "#FFEBEE"
+ errorText: "#CA001B"
+ gold: "#FFD600"
+ highlight: "#FFFBCC"
+ infoBackground: "#ebf5ff"
+ infoText: "#004e8a"
+ link: "#9CC9FF"
+ linkHover: "#82BAFD"
+ mode: "dark"
+ navigation:
+ background: "#0f1214"
+ indicator: "#0066CC"
+ color: "#ffffff"
+ selectedColor: "#ffffff"
+ navItem:
+ hoverBackground: "#3c3f42"
+ submenu:
+ background: "#0f1214"
+ pinSidebarButton:
+ background: "#BDBDBD"
+ icon: "#404040"
+ primary:
+ main: "#1FA7F8"
+ secondary:
+ main: "#B2A3FF"
+ status:
+ aborted: "#9E9E9E"
+ error: "#F84C55"
+ ok: "#71CF88"
+ pending: "#FEF071"
+ running: "#3488E3"
+ warning: "#FFB84D"
+ tabbar:
+ indicator: "#9BF0E1"
+ textContrast: "#FFFFFF"
+ textSubtle: "#CCCCCC"
+ textVerySubtle: "#727272"
+ warningBackground: "#F59B23"
+ warningText: "#000000"
+
+ rhdh:
+ general:
+ disabledBackground: "#444548"
+ disabled: "#AAABAC"
+ searchBarBorderColor: "#57585a"
+ formControlBackgroundColor: "#36373A"
+ mainSectionBackgroundColor: "#0f1214"
+ headerBottomBorderColor: "#A3A3A3"
+ cardBackgroundColor: "#292929"
+ sideBarBackgroundColor: "#1b1d21"
+ cardBorderColor: "#A3A3A3"
+ tableTitleColor: "#E0E0E0"
+ tableSubtitleColor: "#E0E0E0"
+ tableColumnTitleColor: "#E0E0E0"
+ tableRowHover: "#0f1214"
+ tableBorderColor: "#515151"
+ tableBackgroundColor: "#1b1d21"
+ tabsBottomBorderColor: "#444548"
+ contrastText: "#FFF"
+ primary:
+ main: "#1FA7F8"
+ focusVisibleBorder: "#ADD6FF"
+ secondary:
+ main: "#B2A3FF"
+ focusVisibleBorder: "#D0C7FF"
+ cards:
+ headerTextColor: "#FFF"
+ headerBackgroundColor: "#0f1214"
+ headerBackgroundImage: "none"
+----
+
+Alternatively, you can use the following `variant` and `mode` values in the `app-config-rhdh.yaml` file to apply the previous default configuration:
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light:
+ variant: "rhdh"
+ mode: "light"
+ dark:
+ variant: "rhdh"
+ mode: "dark"
+----
+
+== Default {product} page themes
+
+The default {product-short} header color is white in light mode and black in dark mode, as shown in the following `app-config-rhdh.yaml` file configuration:
+
+[source,yaml]
+----
+app:
+ branding:
+ theme:
+ light:
+ palette: {}
+ defaultPageTheme: default
+ pageTheme:
+ default:
+ backgroundColor: "#ffffff"
+ dark:
+ palette: {}
+ defaultPageTheme: default
+ pageTheme:
+ default:
+ backgroundColor: "#0f1214"
+----
diff --git a/modules/discover/con_benefits-of-rhdh.adoc b/modules/discover/con_benefits-of-rhdh.adoc
new file mode 100644
index 0000000000..752fefd83c
--- /dev/null
+++ b/modules/discover/con_benefits-of-rhdh.adoc
@@ -0,0 +1,28 @@
+:_newdoc-version: 2.18.3
+:_template-generated: 2024-10-18
+
+:_mod-docs-content-type: CONCEPT
+
+[id="benefits-of-rhdh_{context}"]
+= Benefits of {product}
+
+{product} is designed to streamline developer workflow by providing a consistent self-service experience and can simplify application development through pre-built resources and enhanced collaboration tools.
+
+The following are the benefits of {product}:
+
+* Increased developer productivity. Increases productivity by eliminating common organizational challenges, enabling seamless collaboration, and providing clear guidelines for creating, developing, and deploying applications.
+
+* Unified self-service dashboard. Provides development teams with a unified dashboard covering various aspects such as Git, CI/CD, SAST/DAST, Supply Chain, OpenShift/Kubernetes cluster, JIRA, monitoring, API, documentation, and more, facilitated by over 150 plugins. All curated by a platform engineering team, aligning with the company’s best practices.
+
+* Best practices through software templates. Automates organizational best practices by encoding common tasks such as creating new applications, running Ansible jobs, and establishing CI/CD pipelines for production deployment in Git.
+
+* Scalable technical documentation. Code and documentation resides in the same repository, eliminating dependencies on proprietary document systems.
+
+* Efficient onboarding for new developers. New developers can adapt quickly and become productive within a short timeframe.
+
+* Robust enterprise Role-Based Access Control (RBAC). Empowers administrators to create roles, assign users or groups to roles, and implement robust security policies for enhanced access control.
+
+
+[role="_additional-resources"]
+.Additional resources
+* For more information about the different features of {product} and how you can extend the upstream Backstage product by providing additional features such as integration with OpenShift, enterprise role-based access control (RBAC), and dynamic plugins, see link:https://developers.redhat.com/rhdh/overview?intcmp=7015Y000003swEuQAI&source=sso[{product}].
\ No newline at end of file
diff --git a/modules/dynamic-plugins/con-ansible-plugin-admin.adoc b/modules/dynamic-plugins/con-ansible-plugin-admin.adoc
new file mode 100644
index 0000000000..2572a6bbed
--- /dev/null
+++ b/modules/dynamic-plugins/con-ansible-plugin-admin.adoc
@@ -0,0 +1,19 @@
+= Installing Ansible plug-ins for {product}
+
+Ansible plug-ins for {product} deliver an Ansible-specific portal experience with curated learning paths,
+push-button content creation, integrated development tools, and other opinionated resources.
+
+[IMPORTANT]
+====
+The Ansible plug-ins are a Technology Preview feature only.
+
+Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+Additional detail on how Red Hat provides support for bundled community dynamic plugins is available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
+
+To install and configure the Ansible plugins, see
+link:https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.4/html/installing_ansible_plug-ins_for_red_hat_developer_hub/index[_Installing Ansible plug-ins for Red Hat Developer Hub_].
+
diff --git a/modules/dynamic-plugins/con-ansible-plugin-user.adoc b/modules/dynamic-plugins/con-ansible-plugin-user.adoc
new file mode 100644
index 0000000000..d8a4c67a91
--- /dev/null
+++ b/modules/dynamic-plugins/con-ansible-plugin-user.adoc
@@ -0,0 +1,19 @@
+= Using Ansible plug-ins for {product}
+
+Ansible plug-ins for {product} deliver an Ansible-specific portal experience with curated learning paths,
+push-button content creation, integrated development tools, and other opinionated resources.
+
+[IMPORTANT]
+====
+The Ansible plug-ins are a Technology Preview feature only.
+
+Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+Additional detail on how Red Hat provides support for bundled community dynamic plugins is available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
+
+To use the Ansible plugins, see
+link:https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.4/html/using_ansible_plug-ins_for_red_hat_developer_hub/index[_Using Ansible plug-ins for Red Hat Developer Hub_].
+
diff --git a/modules/dynamic-plugins/con-ansible-plugin.adoc b/modules/dynamic-plugins/con-ansible-plugin.adoc
new file mode 100644
index 0000000000..6b38258a64
--- /dev/null
+++ b/modules/dynamic-plugins/con-ansible-plugin.adoc
@@ -0,0 +1,26 @@
+= Installing and using Ansible plug-ins for {product}
+
+Ansible plug-ins for {product} deliver an Ansible-specific portal experience with curated learning paths,
+push-button content creation, integrated development tools, and other opinionated resources.
+
+[IMPORTANT]
+====
+The Ansible plug-ins are a Technology Preview feature only.
+
+Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend using them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
+
+For more information on Red Hat Technology Preview features, see https://access.redhat.com/support/offerings/techpreview/[Technology Preview Features Scope].
+
+Additional detail on how Red Hat provides support for bundled community dynamic plugins is available on the https://access.redhat.com/policy/developerhub-support-policy[Red Hat Developer Support Policy] page.
+====
+
+== For administrators
+
+To install and configure the Ansible plugins, see
+link:https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.4/html/installing_ansible_plug-ins_for_red_hat_developer_hub/index[_Installing Ansible plug-ins for Red Hat Developer Hub_].
+
+== For users
+
+To use the Ansible plugins, see
+link:https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.4/html/using_ansible_plug-ins_for_red_hat_developer_hub/index[_Using Ansible plug-ins for Red Hat Developer Hub_].
+
diff --git a/modules/dynamic-plugins/con-basic-config-dynamic-plugins.adoc b/modules/dynamic-plugins/con-basic-config-dynamic-plugins.adoc
new file mode 100644
index 0000000000..149135fe03
--- /dev/null
+++ b/modules/dynamic-plugins/con-basic-config-dynamic-plugins.adoc
@@ -0,0 +1,15 @@
+[id="con-basic-config-dynamic-plugins"]
+
+= Basic configuration of dynamic plugins
+
+Some dynamic plugins require environment variables to be set. If a mandatory environment variable is not set, and the plugin is enabled, then the application might fail at startup.
+
+//The mandatory environment variables for each plugin are listed in the xref:rhdh-supported-plugins[Dynamic plugins support matrix].
+
+[NOTE]
+====
+Zib-bomb detection
+When installing some dynamic plugin containing large files, if the installation script considers the package archive to be a Zib-Bomb, the installation fails.
+
+To increase the maximum permitted size of a file inside a package archive, you can increase the `MAX_ENTRY_SIZE` environment value of the deployment `install-dynamic-plugins initContainer` from the default size of `20000000` bytes.
+====
diff --git a/modules/dynamic-plugins/con-dynamic-plugins-cache.adoc b/modules/dynamic-plugins/con-dynamic-plugins-cache.adoc
new file mode 100644
index 0000000000..141d0819c5
--- /dev/null
+++ b/modules/dynamic-plugins/con-dynamic-plugins-cache.adoc
@@ -0,0 +1,68 @@
+[id="con-dynamic-plugin-cache_{context}"]
+
+= Using the dynamic plugins cache
+The dynamic plugins cache in {product} ({product-very-short}) enhances the installation process and reduces platform boot time by storing previously installed plugins. If the configuration remains unchanged, this feature prevents the need to re-download plugins on subsequent boots.
+
+When you enable dynamic plugins cache:
+
+* The system calculates a checksum of each plugin's YAML configuration (excluding `pluginConfig`).
+* The checksum is stored in a file named `dynamic-plugin-config.hash` within the plugin's directory.
+* During boot, if a plugin's package reference matches the previous installation and the checksum is unchanged, the download is skipped.
+* Plugins that are disabled since the previous boot are automatically removed.
+
+== Enabling the dynamic plugins cache
+To enable the dynamic plugins cache in {product-very-short}, the plugins directory `dynamic-plugins-root` must be a persistent volume.
+
+For Helm chart installations, a persistent volume named `dynamic-plugins-root` is automatically created.
+
+For operator-based installations, you must manually create the PersistentVolumeClaim (PVC) as follows:
+
+[source,yaml]
+----
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: dynamic-plugins-root
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 5Gi
+
+---
+
+apiVersion: rhdh.redhat.com/v1alpha2
+kind: Backstage
+metadata:
+ name: developer-hub
+spec:
+ deployment:
+ patch:
+ spec:
+ template:
+ spec:
+ volumes:
+ - $patch: replace
+ name: dynamic-plugins-root
+ persistentVolumeClaim:
+ claimName: dynamic-plugins-root
+----
+
+[NOTE]
+====
+Future versions of the {product-very-short} operator are planned to automatically create the PVC.
+====
+
+== Configuring the dynamic plugins cache
+You can set the following optional dynamic plugin cache parameters:
+
+* `forceDownload`: Set to `true` to force a reinstall of the plugin, bypassing the cache. Default is `false`. For example, modify your `dynamic-plugins.yaml` file as follows:
++
+[source,yaml]
+----
+plugins:
+ - disabled: false
+ forceDownload: true
+ package: 'oci://quay.io/example-org/example-plugin:v1.0.0!internal-backstage-plugin-example'
+----
diff --git a/modules/dynamic-plugins/con-install-dynamic-plugin-helm.adoc b/modules/dynamic-plugins/con-install-dynamic-plugin-helm.adoc
new file mode 100644
index 0000000000..23d624207c
--- /dev/null
+++ b/modules/dynamic-plugins/con-install-dynamic-plugin-helm.adoc
@@ -0,0 +1,24 @@
+// Module included in the following assemblies:
+//
+// * assemblies/assembly-rhdh-installing-dynamic-plugins.adoc
+// * assemblies/dynamic-plugins/assembly-rhdh-installing-dynamic-plugins.adoc
+
+:_mod-docs-content-type: CONCEPT
+[id="con-install-dynamic-plugin-helm_{context}"]
+= Installing dynamic plugins using the Helm chart
+
+You can deploy a {product-short} instance using a Helm chart, which is a flexible installation method. With the Helm chart, you can sideload dynamic plugins into your {product-short} instance without having to recompile your code or rebuild the container.
+
+To install dynamic plugins in {product-short} using Helm, add the following `global.dynamic` parameters in your Helm chart:
+
+* `plugins`: the dynamic plugins list intended for installation. By default, the list is empty. You can populate the plugins list with the following fields:
+** `package`: a package specification for the dynamic plugin package that you want to install. You can use a package for either a local or an external dynamic plugin installation. For a local installation, use a path to the local folder containing the dynamic plugin. For an external installation, use a package specification from a public NPM repository.
+** `integrity` (required for external packages): an integrity checksum in the form of `-` specific to the package. Supported algorithms include `sha256`, `sha384` and `sha512`.
+** `pluginConfig`: an optional plugin-specific `app-config` YAML fragment. See plugin configuration for more information.
+** `disabled`: disables the dynamic plugin if set to `true`. Default: `false`.
+* `includes`: a list of YAML files utilizing the same syntax.
+
+[NOTE]
+====
+The `plugins` list in the `includes` file is merged with the `plugins` list in the main Helm values. If a plugin package is mentioned in both `plugins` lists, the `plugins` fields in the main Helm values override the `plugins` fields in the `includes` file. The default configuration includes the `dynamic-plugins.default.yaml` file, which contains all of the dynamic plugins preinstalled in {product-short}, whether enabled or disabled by default.
+====
diff --git a/modules/dynamic-plugins/con-preinstalled-dynamic-plugins.adoc b/modules/dynamic-plugins/con-preinstalled-dynamic-plugins.adoc
new file mode 100644
index 0000000000..5d3d275937
--- /dev/null
+++ b/modules/dynamic-plugins/con-preinstalled-dynamic-plugins.adoc
@@ -0,0 +1,36 @@
+[id="con-preinstalled-dynamic-plugins"]
+= Preinstalled dynamic plugins
+
+{product} is preinstalled with a selection of dynamic plugins.
+//For a complete list of dynamic plugins that are included in this release of {product-short}, see the xref:rhdh-supported-plugins[Dynamic plugins support matrix].
+
+The following preinstalled dynamic plugins are enabled by default:
+
+* `@janus-idp/backstage-plugin-analytics-provider-segment`
+* `@janus-idp/backstage-scaffolder-backend-module-quay`
+* `@janus-idp/backstage-scaffolder-backend-module-regex`
+* `@backstage/plugin-techdocs-backend`
+* `@backstage/plugin-techdocs`
+
+Upon application startup, for each plugin that is disabled by default, the `install-dynamic-plugins init container` within the {product-short} pod log displays a message similar to the following:
+
+[source,yaml]
+----
+======= Skipping disabled dynamic plugin ./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic
+----
+
+To enable this plugin, add a package with the same name to the Helm chart and change the value in the `disabled` field to ‘false’. For example:
+
+[source,java]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic
+ disabled: false
+----
+
+[NOTE]
+The default configuration for a plugin is extracted from the `dynamic-plugins.default.yaml` file, however, you can use a `pluginConfig` entry to override the default configuration.
diff --git a/modules/dynamic-plugins/con-preinstalled-dynamic-plugins.template.adoc b/modules/dynamic-plugins/con-preinstalled-dynamic-plugins.template.adoc
new file mode 100644
index 0000000000..8f125e6475
--- /dev/null
+++ b/modules/dynamic-plugins/con-preinstalled-dynamic-plugins.template.adoc
@@ -0,0 +1,34 @@
+[id="con-preinstalled-dynamic-plugins"]
+
+= Preinstalled dynamic plugins
+
+{product} is preinstalled with a selection of dynamic plugins. For a complete list of dynamic plugins that are included in this release of {product-short}, see the xref:rhdh-supported-plugins[Dynamic plugins support matrix].
+
+The following preinstalled dynamic plugins are enabled by default:
+
+%%ENABLED_PLUGINS%%
+
+The dynamic plugins that require custom configuration are disabled by default.
+
+Upon application startup, for each plugin that is disabled by default, the `install-dynamic-plugins init container` within the {product-short} pod log displays a message similar to the following:
+
+[source,yaml]
+----
+======= Skipping disabled dynamic plugin ./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic
+----
+
+To enable this plugin, add a package with the same name to the Helm chart and change the value in the `disabled` field to ‘false’. For example:
+
+[source,java]
+----
+global:
+ dynamic:
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: ./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic
+ disabled: false
+----
+
+[NOTE]
+The default configuration for a plugin is extracted from the `dynamic-plugins.default.yaml` file, however, you can use a `pluginConfig` entry to override the default configuration.
diff --git a/modules/dynamic-plugins/con-rhdh-plugins.adoc b/modules/dynamic-plugins/con-rhdh-plugins.adoc
new file mode 100644
index 0000000000..a52508f8b2
--- /dev/null
+++ b/modules/dynamic-plugins/con-rhdh-plugins.adoc
@@ -0,0 +1,71 @@
+[id="con-rhdh-plugins"]
+
+= Plugins in {product}
+
+// The {product} application offers a unified platform with various plugins. Using the plugin ecosystem within the {product-short} application, you can access any kind of development infrastructure or software development tool.
+
+// The plugins in {product-short} maximize the productivity and streamline the development workflows by maintaining the consistency in the overall user experience.
+
+The {product} ({product-very-short}) application offers a unified platform with various plugins. Using the plugin ecosystem within the {product-very-short} application, you can access any kind of development infrastructure or software development tool.
+
+Plugins are modular extensions for {product-very-short} that extend functionality, streamline development workflows, and improve the developer experience. You can add and configure plugins in {product-very-short} to access various software development tools.
+
+Each plugin is designed as a self-contained application and can incorporate any type of content. The plugins utilize a shared set of platform APIs and reusable UI components. Plugins can also retrieve data from external sources through APIs or by relying on external modules to perform the tasks.
+
+{product-very-short} provides both static and dynamic plugins that enhance its functionality. Static plugins are integrated into the core of the {product-very-short} application, while dynamic plugins can be sideloaded into your {product-short} instance without the need to recompile your code or rebuild the container.
+
+To install or update a static plugin you must update your {product-very-short} application source code and rebuild the application and container image.
+
+To install or update a dynamic plugin, you must restart your {product-very-short} application source code after installing the plugin.
+
+You can also import your own custom-built or third-party plugins or create new features using dynamic plugins.
+
+
+Dynamic plugins boost modularity and scalability by enabling more flexible and efficient functionality loading, significantly enhancing the developer experience and customization of your {product-very-short} instance.
+
+== Dynamic plugins in {product}
+You can use {product-very-short} dynamic plugins in environments where flexibility, scalability, and customization are key. Using dynamic plugins in {product-very-short} provides:
+
+Modularity and extensibility::
+You can add or modify features without altering the core {product-very-short} application. This modular approach makes it easier to extend functionality as needs evolve.
+
+Customization::
+You can tailor {product-very-short} to fit specific workflows and use cases, enhancing the overall user experience.
+
+Reduced maintenance and update overhead::
+You can deploy the updates or new features independently of the main {product-very-short} codebase, reducing the risks and efforts associated with maintaining and updating the platform.
+
+Faster iteration::
+You can create and test new features more rapidly as plugins, encouraging experimentation and enabling you to quickly iterate based on feedback.
+
+Improved collaboration::
+You can share plugins across teams or even externally. This sharing can foster collaboration and reduce duplication of effort, as well as help establish best practices across an organization.
+
+Scalability::
+As organizations grow, their needs become complex. Dynamic plugins enable {product-very-short} to scale alongside such complex needs, accommodating an increasing number of users and services.
+
+Ecosystem growth::
+Fostering the development of plugins can create a dynamic ecosystem around {product-very-short}. This community can contribute to plugins that cater to different needs, thereby enhancing the platform.
+
+Security and compliance::
+You can develop plugins with specific security and compliance requirements in mind, ensuring that {product-very-short} installations meet the necessary standards without compromising the core application.
+
+Overall, the use of dynamic plugins in {product-very-short} promotes a flexible, adaptable, and sustainable approach to managing and scaling development infrastructure.
+
+== Comparing dynamic plugins to static plugins
+Static plugins are built into the core of the {product-very-short} application. Installing or updating a static plugin requires a restart of the application after installing the plugin.
+
+The following table provides a comparison between static and dynamic plugins in {product-very-short}.
+
+[%header,cols=3*]
+|===
+|*Feature* |*Static plugins* |*Dynamic plugins*
+|Integration |Built into the core application. |Loaded at runtime, separate from the core.
+|Flexibility |Requires core changes to add or update features. |Add or update features without core changes.
+|Development speed |Slower, requires a complete rebuild for new
+features. |Faster, deploy new functionalities quickly.
+|Customization |Limited to predefined options. |Easy to tailor platform by loading specific plugins.
+|Maintenance |More complex due to tightly coupled features. |Enhanced by modular architecture.
+|Resource use |All features loaded at startup. |Only necessary plugins loaded dynamically.
+|Innovation |Slower experimentation due to rebuild cycles. |Quick experimentation with new plugins.
+|===
\ No newline at end of file
diff --git a/modules/dynamic-plugins/proc-config-dynamic-plugins-rhdh-operator.adoc b/modules/dynamic-plugins/proc-config-dynamic-plugins-rhdh-operator.adoc
new file mode 100644
index 0000000000..08cbbf40c6
--- /dev/null
+++ b/modules/dynamic-plugins/proc-config-dynamic-plugins-rhdh-operator.adoc
@@ -0,0 +1,98 @@
+// Module included in the following assemblies:
+//
+// * assemblies/assembly-install-rhdh-ocp.adoc
+
+:_mod-docs-content-type: PROCEDURE
+[id="proc-config-dynamic-plugins-rhdh-operator_{context}"]
+= Installing dynamic plugins with the {product} Operator
+
+You can store the configuration for dynamic plugins in a `ConfigMap` object that your `Backstage` custom resource (CR) can reference.
+
+[NOTE]
+====
+If the `pluginConfig` field references environment variables, you must define the variables in your `secrets-rhdh` secret.
+====
+
+.Procedure
+
+. From the {ocp-short} web console, select the *ConfigMaps* tab.
+. Click *Create ConfigMap*.
+. From the *Create ConfigMap* page, select the *YAML view* option in *Configure via* and edit the file, if needed.
++
+.Example `ConfigMap` object using the GitHub dynamic plugin
+[source, yaml]
+----
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: dynamic-plugins-rhdh
+data:
+ dynamic-plugins.yaml: |
+ includes:
+ - dynamic-plugins.default.yaml
+ plugins:
+ - package: './dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic'
+ disabled: false
+ pluginConfig:
+ catalog:
+ providers:
+ github:
+ organization: "${GITHUB_ORG}"
+ schedule:
+ frequency: { minutes: 1 }
+ timeout: { minutes: 1 }
+ initialDelay: { seconds: 100 }
+----
+
+. Click *Create*.
+. Go to the *Topology* view.
+. Click on the overflow menu for the {product} instance that you want to use and select *Edit Backstage* to load the YAML view of the {product} instance.
++
+image::rhdh/operator-install-2.png[]
+
+. Add the `dynamicPluginsConfigMapName` field to your `Backstage` CR. For example:
++
+[source,yaml]
+----
+apiVersion: rhdh.redhat.com/v1alpha1
+kind: Backstage
+metadata:
+ name: my-rhdh
+spec:
+ application:
+# ...
+ dynamicPluginsConfigMapName: dynamic-plugins-rhdh
+# ...
+----
+. Click *Save*.
+. Navigate back to the *Topology* view and wait for the {product} pod to start.
+. Click the *Open URL* icon to start using the {product} platform with the new configuration changes.
+
+.Verification
+
+* Ensure that the dynamic plugins configuration has been loaded, by appending `/api/dynamic-plugins-info/loaded-plugins` to your {product} root URL and checking the list of plugins:
++
+.Example list of plugins
+[source,json]
+----
+[
+ {
+ "name": "backstage-plugin-catalog-backend-module-github-dynamic",
+ "version": "0.5.2",
+ "platform": "node",
+ "role": "backend-plugin-module"
+ },
+ {
+ "name": "backstage-plugin-techdocs",
+ "version": "1.10.0",
+ "role": "frontend-plugin",
+ "platform": "web"
+ },
+ {
+ "name": "backstage-plugin-techdocs-backend-dynamic",
+ "version": "1.9.5",
+ "platform": "node",
+ "role": "backend-plugin"
+ },
+]
+----
diff --git a/modules/dynamic-plugins/proc-installing-and-configuring-redis-cache.adoc b/modules/dynamic-plugins/proc-installing-and-configuring-redis-cache.adoc
new file mode 100644
index 0000000000..f0434f2487
--- /dev/null
+++ b/modules/dynamic-plugins/proc-installing-and-configuring-redis-cache.adoc
@@ -0,0 +1,37 @@
+[id="proc-installing-and-configuring-redis-cache_{context}"]
+= Using Redis Cache with dynamic plugins
+You can use the Redis cache store to improve {product-very-short} performance and reliability. Plugins in {product-very-short} receive dedicated cache connections, which are powered by Keyv.
+
+== Installing Redis Cache in {product}
+
+.Prerequisites
+* You have installed Red Hat Developer Hub by using either the Operator or Helm chart.
+* You have an active Redis server. For more information on setting up an external Redis server, see the link:https://www.redis.io/docs/latest/[`Redis official documentation`].
+
+.Procedure
+Add the following code to your `app-config.yaml` file:
+[source, yaml]
+----
+backend:
+ cache:
+ store: redis
+ connection: redis://user:pass@cache.example.com:6379
+ useRedisSets: true
+----
+
+== Configuring Redis Cache in {product}
+=== useRedisSets
+The `useRedisSets` option lets you decide whether to use Redis sets for key management. By default, this option is set to `true`.
+
+When `useRedisSets` is enabled (`true`):
+
+* A namespace for the Redis sets is created, and all generated keys are added to that namespace, enabling group management of the keys.
+
+* When a key is deleted, it's removed from the main storage and the Redis set.
+
+* When using the clear function to delete all keys, every key in the Redis set is checked for deletion, and the set itself is also removed.
+
+[NOTE]
+In high-performance scenarios, enabling `useRedisSets` can result in memory leaks. If you are running a high-performance application or service, you must set `useRedisSets` to `false`.
+
+When you set `useRedisSets` to `false`, the keys are handled individually and Redis sets are not utilized. This configuration might lead to performance issues in production when using the `clear` function, as it requires iterating over all keys for deletion.
\ No newline at end of file
diff --git a/modules/dynamic-plugins/proc-obtaining-integrity-checksum.adoc b/modules/dynamic-plugins/proc-obtaining-integrity-checksum.adoc
new file mode 100644
index 0000000000..3b35ad2a07
--- /dev/null
+++ b/modules/dynamic-plugins/proc-obtaining-integrity-checksum.adoc
@@ -0,0 +1,9 @@
+[id="proc-obtaining-integrity-checksum"]
+
+= Obtaining the integrity checksum
+
+To obtain the integrity checksum, enter the following command:
+
+----
+npm view