aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoan Luu Duc Tai <doan@luuduct.ai>2026-10-30 16:29:50 -0500
committerDoan Luu Duc Tai <doan@luuduct.ai>2026-10-30 16:29:50 -0500
commitd611c869eb12e7fff5754be31775f82200ec958b (patch)
tree835aa0f83b7c7c62d61044a196506ac232b2a1cc
parent1206813d47e8602f08cbeaf27e73453e089e7c52 (diff)
Render the license page in cgit and stack the site footer linksHEADmain
-rw-r--r--docs/OPERATIONS.txt9
-rw-r--r--infra/containers/cgit/cgitrc2
-rw-r--r--infra/containers/cgit/cgitrc.local2
-rw-r--r--infra/containers/cgit/license.lua47
-rw-r--r--infra/services.toml1
-rw-r--r--web/index.html9
-rw-r--r--web/styles.css22
7 files changed, 88 insertions, 4 deletions
diff --git a/docs/OPERATIONS.txt b/docs/OPERATIONS.txt
index 604cefb..826c4cf 100644
--- a/docs/OPERATIONS.txt
+++ b/docs/OPERATIONS.txt
@@ -321,3 +321,12 @@ RECOVERY LIMITS AND SECRET ROTATION
historical Python recovery helper. Keep that helper with those exports.
The current command intentionally accepts only its verified format-2
archives. Fresh format-2 production backups replace the normal workflow.
+
+LICENSE PAGE IN CGIT
+
+ The stack repository's About tab renders only
+ web/THIRD-PARTY-LICENSES.html. Source and Raw links retain the normal cgit
+ views and preserve revision queries. Other files are not rendered as HTML.
+ The rendered document is isolated in a sandboxed frame, with scripts and
+ external resources blocked. The standalone website license page remains
+ available at /THIRD-PARTY-LICENSES.html.
diff --git a/infra/containers/cgit/cgitrc b/infra/containers/cgit/cgitrc
index 0b563e0..9aaf8d5 100644
--- a/infra/containers/cgit/cgitrc
+++ b/infra/containers/cgit/cgitrc
@@ -24,4 +24,6 @@ defbranch=main
cache-root=/var/cache/cgit
cache-size=1000
cache-scanrc-ttl=1
+readme=:web/THIRD-PARTY-LICENSES.html
+about-filter=lua:/etc/cgit-license.lua
scan-path=/srv/git
diff --git a/infra/containers/cgit/cgitrc.local b/infra/containers/cgit/cgitrc.local
index 3c8d657..20b533a 100644
--- a/infra/containers/cgit/cgitrc.local
+++ b/infra/containers/cgit/cgitrc.local
@@ -24,4 +24,6 @@ defbranch=main
cache-root=/var/cache/cgit
cache-size=1000
cache-scanrc-ttl=1
+readme=:web/THIRD-PARTY-LICENSES.html
+about-filter=lua:/etc/cgit-license.lua
scan-path=/srv/git
diff --git a/infra/containers/cgit/license.lua b/infra/containers/cgit/license.lua
new file mode 100644
index 0000000..ff5685f
--- /dev/null
+++ b/infra/containers/cgit/license.lua
@@ -0,0 +1,47 @@
+-- Copyright (C) 2026 Doan Luu Duc Tai <doan@luuduct.ai>
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU Affero General Public License as
+-- published by the Free Software Foundation, either version 3 of the
+-- License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU Affero General Public License for more details.
+--
+-- You should have received a copy of the GNU Affero General Public License
+-- along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+local chunks = {}
+local rendered = false
+
+function filter_open(filename)
+ chunks = {}
+ rendered = filename == "web/THIRD-PARTY-LICENSES.html"
+end
+
+function filter_write(buffer)
+ if rendered then
+ chunks[#chunks + 1] = buffer
+ else
+ html_txt(buffer)
+ end
+end
+
+function filter_close()
+ if rendered then
+ local query = os.getenv("QUERY_STRING") or ""
+ local suffix = query ~= "" and ("?" .. query) or ""
+ html('<nav aria-label="License views"><strong>Rendered</strong> | <a href="')
+ html_attr("../tree/web/THIRD-PARTY-LICENSES.html" .. suffix)
+ html('">Source</a> | <a href="')
+ html_attr("../plain/web/THIRD-PARTY-LICENSES.html" .. suffix)
+ html('">Raw</a></nav>')
+ html('<iframe title="Third-party licenses" sandbox="" referrerpolicy="no-referrer" style="width:100%;height:80vh;border:0" srcdoc="')
+ html_attr([[<!doctype html><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'">]])
+ html_attr(table.concat(chunks))
+ html('"></iframe>')
+ end
+ return 0
+end
diff --git a/infra/services.toml b/infra/services.toml
index 97091cf..f352d68 100644
--- a/infra/services.toml
+++ b/infra/services.toml
@@ -33,6 +33,7 @@ health = ["curl", "--fail", "--silent", "--max-time", "3", "http://127.0.0.1:808
mounts = [
{ source = "var/data/repos", target = "/srv/git", read_only = true },
{ source = "@cgit", target = "/etc/cgitrc", read_only = true },
+ { source = "infra/containers/cgit/license.lua", target = "/etc/cgit-license.lua", read_only = true },
]
tmpfs = ["/run", "/var/cache/cgit"]
diff --git a/web/index.html b/web/index.html
index 4d808a8..527a70d 100644
--- a/web/index.html
+++ b/web/index.html
@@ -79,10 +79,11 @@ ________________________________________________________________________________
</pre>
- <div class="source-footer">
- <a href="https://git.doan.luuduct.ai/stack/tree/web/index.html">[ Source Code ]</a>
- <a href="/THIRD-PARTY-LICENSES.html">[ Third-party Licenses ]</a>
- </div>
+ <nav class="source-footer" aria-label="Licensing and source">
+ <a class="project-license" href="https://www.gnu.org/licenses/agpl-3.0.html">[ LICENSE ]</a>
+ <a class="dependency-licenses" href="https://git.doan.luuduct.ai/stack/about/">[ THIRD PARTY LICENSES ]</a>
+ <a href="https://git.doan.luuduct.ai/stack/tree/web/index.html">[ SOURCE CODE ]</a>
+ </nav>
</div>
</div>
diff --git a/web/styles.css b/web/styles.css
index f2f158c..a50bc37 100644
--- a/web/styles.css
+++ b/web/styles.css
@@ -110,8 +110,30 @@ a {
}
.source-footer {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ gap: 0.5em;
text-align: right;
margin-top: 32px;
margin-bottom: 16px;
font-weight: bold;
}
+
+.source-footer .project-license {
+ color: #923900;
+}
+
+.source-footer .dependency-licenses {
+ color: #355b3c;
+}
+
+@media (prefers-color-scheme: dark) {
+ .source-footer .project-license {
+ color: #efb366;
+ }
+
+ .source-footer .dependency-licenses {
+ color: #a3c7a8;
+ }
+}