This is an automated email from the ASF dual-hosted git repository.
imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph-computer.git
The following commit(s) were added to refs/heads/master by this push:
new 60bb1b65 fix(vermeer): add Web UI build pipeline (#348)
60bb1b65 is described below
commit 60bb1b659cdd23089fd37ca542a18e68d9cf8225
Author: lokidundun <[email protected]>
AuthorDate: Tue Jun 2 15:06:49 2026 +0800
fix(vermeer): add Web UI build pipeline (#348)
* add license
* Add release metadata to Docker image and add Vermeer CI workflow
---
.github/workflows/vermeer-ci.yml | 109 +++++++++
README.md | 2 +-
vermeer/.dockerignore | 22 +-
vermeer/.gitignore | 8 +
vermeer/Dockerfile | 3 +
vermeer/Makefile | 25 ++-
vermeer/README.md | 49 ++++-
vermeer/asset/asset.go | 2 +-
vermeer/asset/asset_dev_ui.go | 2 +-
vermeer/build.sh | 14 +-
vermeer/config/worker.ini | 5 +-
vermeer/release-docs/LICENSE | 244 +++++++++++++++++++++
vermeer/release-docs/NOTICE | 44 ++++
.../release-docs/licenses/LICENSE-bootstrap.txt | 22 ++
.../licenses/LICENSE-bootstrap4-glyphicons.txt | 201 +++++++++++++++++
.../release-docs/licenses/LICENSE-fontawesome.txt | 110 ++++++++++
.../release-docs/licenses/LICENSE-glyphicons.txt | 26 +++
vermeer/release-docs/licenses/LICENSE-jquery.txt | 22 ++
vermeer/scripts/download_ui_assets.sh | 177 +++++++++++++++
vermeer/ui/package.json | 10 +
vermeer/ui/ui/lib/functions.js | 187 ++++++++++++++++
vermeer/ui/ui/lib/vermeer.css | 53 +++++
22 files changed, 1315 insertions(+), 22 deletions(-)
diff --git a/.github/workflows/vermeer-ci.yml b/.github/workflows/vermeer-ci.yml
new file mode 100644
index 00000000..777ecfce
--- /dev/null
+++ b/.github/workflows/vermeer-ci.yml
@@ -0,0 +1,109 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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: "Vermeer CI"
+
+on:
+ push:
+ branches:
+ - master
+ - /^release-.*$/
+ paths:
+ - vermeer/**
+ - .github/workflows/vermeer-ci.yml
+ pull_request:
+ paths:
+ - vermeer/**
+ - .github/workflows/vermeer-ci.yml
+
+defaults:
+ run:
+ working-directory: vermeer
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ vermeer-build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: '1.23'
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+
+ - name: Cache Go modules
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/go/pkg/mod
+ ~/.cache/go-build
+ key: ${{ runner.os }}-go-${{ hashFiles('vermeer/go.sum') }}
+ restore-keys: ${{ runner.os }}-go-
+
+ - name: Download Go modules
+ run: go mod download
+
+ - name: Download UI assets
+ run: ./scripts/download_ui_assets.sh
+
+ - name: Generate embedded assets
+ run: cd asset && go generate
+
+ - name: Build
+ run: CGO_ENABLED=0 go build -o vermeer
+
+ - name: Verify binary exists
+ run: test -x vermeer
+
+ - name: Verify release metadata exists
+ run: |
+ test -f release-docs/LICENSE
+ test -f release-docs/NOTICE
+ test -d release-docs/licenses
+
+ vermeer-docker:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build Docker image (dry-run)
+ uses: docker/build-push-action@v6
+ with:
+ context: vermeer
+ push: false
+ tags: vermeer:ci-check
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+
+ - name: Verify release metadata in image
+ run: |
+ docker run --rm --entrypoint test vermeer:ci-check -f
/go/bin/release-docs/LICENSE
+ docker run --rm --entrypoint test vermeer:ci-check -f
/go/bin/release-docs/NOTICE
+ docker run --rm --entrypoint test vermeer:ci-check -d
/go/bin/release-docs/licenses
diff --git a/README.md b/README.md
index c9fda699..2f742e16 100644
--- a/README.md
+++ b/README.md
@@ -146,7 +146,7 @@ For quick start and single-machine deployments, we
recommend **Vermeer**:
# Pull the image
docker pull hugegraph/vermeer:latest
-# Change config path in docker-compose.yml
+# Change config path in docker-compose.yaml
volumes:
- ~/:/go/bin/config # Change here to your actual config path, e.g.,
vermeer/config
diff --git a/vermeer/.dockerignore b/vermeer/.dockerignore
index 6e8f887b..697abfb0 100644
--- a/vermeer/.dockerignore
+++ b/vermeer/.dockerignore
@@ -14,6 +14,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-*data*
-*test*
-*.git*
\ No newline at end of file
+.git/
+.gitignore
+.gitattributes
+test/
+vermeer_test.go
+vermeer_test.sh
+vermeer_data/
+asset/assets_vfsdata.go
+ui/node_modules/
+ui/package-lock.json
+ui/ui/lib/bootstrap-4.3.1-dist/
+ui/ui/lib/bootstrap4-glyphicons/
+ui/ui/lib/jquery-3.5.1.min.js
+ui/ui/lib/jquery-license
+_tmp_extractor/
+tools/supervisord/*/supervisord
+tools/protoc/*/protoc
+tools/protoc/*/bin/
+tools/protoc/*/include/
\ No newline at end of file
diff --git a/vermeer/.gitignore b/vermeer/.gitignore
index 8fb775a2..9907f62d 100644
--- a/vermeer/.gitignore
+++ b/vermeer/.gitignore
@@ -99,6 +99,14 @@ tools/protoc/*/include/
######################
asset/assets_vfsdata.go
+# UI dependencies (downloaded via scripts/download_ui_assets.sh) #
+######################
+ui/node_modules/
+ui/package-lock.json
+ui/ui/lib/*
+!ui/ui/lib/functions.js
+!ui/ui/lib/vermeer.css
+
# AI assistant specific files (we only maintain AGENTS.md) #
######################
CLAUDE.md
diff --git a/vermeer/Dockerfile b/vermeer/Dockerfile
index 75a65bf6..44da2502 100644
--- a/vermeer/Dockerfile
+++ b/vermeer/Dockerfile
@@ -15,9 +15,11 @@
# limitations under the License.
#
FROM golang:1.23-alpine AS builder
+RUN apk add --no-cache npm bash curl
COPY ./ /src/
WORKDIR /src/
ENV CGO_ENABLED="0"
+RUN ./scripts/download_ui_assets.sh
RUN cd asset && go generate
RUN go build -o /go/bin/app
@@ -25,6 +27,7 @@ FROM alpine
EXPOSE 8080
COPY --from=builder /go/bin/app /go/bin/app
COPY --from=builder /src/config/ /go/bin/config/
+COPY --from=builder /src/release-docs/ /go/bin/release-docs/
COPY --from=builder /usr/local/go/lib/time/zoneinfo.zip /
ENV TZ=Asia/Shanghai
ENV ZONEINFO=/zoneinfo.zip
diff --git a/vermeer/Makefile b/vermeer/Makefile
index ba9cb73f..1bc765c3 100644
--- a/vermeer/Makefile
+++ b/vermeer/Makefile
@@ -15,13 +15,13 @@
# limitations under the License.
#
-.PHONY: all init download-binaries generate-assets build clean help
+.PHONY: all init download-binaries download-ui-assets generate-assets build
clean help
# Default target
all: generate-assets build
# Initialize project (first time setup)
-init: download-binaries
+init: download-binaries download-ui-assets
@echo "Installing Go dependencies..."
go mod download
@echo "Project initialized successfully!"
@@ -31,8 +31,17 @@ download-binaries:
@echo "Downloading binary dependencies..."
@./scripts/download_binaries.sh || (echo "Failed to download binaries"
&& exit 1)
+# Download UI assets (jQuery, Bootstrap, Glyphicons)
+download-ui-assets:
+ @if [ ! -f "ui/ui/lib/.downloaded" ]; then \
+ echo "Downloading UI assets..."; \
+ ./scripts/download_ui_assets.sh || (echo "Failed to download UI
assets" && exit 1); \
+ else \
+ echo "UI assets already exist, skipping download."; \
+ fi
+
# Generate assets (vfsdata.go for web UI)
-generate-assets:
+generate-assets: download-ui-assets
@echo "Generating assets..."
@cd asset && go generate || (echo "Failed to generate assets" && exit 1)
@echo "Assets generated successfully!"
@@ -66,6 +75,11 @@ clean-all: clean
@rm -rf tools/protoc/*/protoc
@rm -rf tools/protoc/*/bin
@rm -rf tools/protoc/*/include
+ @echo "Cleaning downloaded UI assets..."
+ @rm -rf ui/node_modules ui/package-lock.json
+ @rm -f ui/ui/lib/.downloaded ui/ui/lib/jquery-license
+ @rm -rf ui/ui/lib/bootstrap-*-dist ui/ui/lib/bootstrap4-glyphicons
+ @rm -f ui/ui/lib/jquery-*.min.js
@echo "All clean completed!"
# Help
@@ -73,13 +87,14 @@ help:
@echo "Vermeer Build System"
@echo ""
@echo "Usage:"
- @echo " make init - First time setup (download binaries +
go mod download)"
+ @echo " make init - First time setup (download binaries +
UI assets + go mod download)"
@echo " make download-binaries - Download supervisord and protoc
binaries for your platform"
+ @echo " make download-ui-assets - Download jQuery, Bootstrap,
Glyphicons to ui/ui/lib/"
@echo " make generate-assets - Generate assets_vfsdata.go from web
UI (required before build)"
@echo " make build - Build vermeer for current platform
(default: local architecture)"
@echo " make build-linux-amd64 - Build for Linux AMD64 (for
deployment)"
@echo " make build-linux-arm64 - Build for Linux ARM64 (for ARM
servers)"
@echo " make clean - Remove generated files and binaries
(keep downloaded tools)"
- @echo " make clean-all - Remove everything including
downloaded tools"
+ @echo " make clean-all - Remove everything including
downloaded tools and UI assets"
@echo " make all - Generate assets and build (default
target)"
@echo " make help - Show this help message"
diff --git a/vermeer/README.md b/vermeer/README.md
index 38425637..97cf58d7 100644
--- a/vermeer/README.md
+++ b/vermeer/README.md
@@ -89,7 +89,12 @@ vermeer/
│ ├── master.ini
│ └── worker.ini
├── tools/ # Binary dependencies (supervisord, protoc)
-└── ui/ # Web dashboard
+└── ui/ # Web dashboard source and dependencies
+ ├── package.json # Frontend dependencies (jQuery, Bootstrap)
+ └── ui/
+ ├── master.html # Master dashboard page
+ ├── worker.html # Worker dashboard page
+ └── lib/ # Downloaded at build time (git-ignored)
```
## Quick Start
@@ -107,8 +112,8 @@ Create a dedicated config directory (e.g.,
`~/vermeer-config/`) with `master.ini
Run with Docker:
```bash
-# Master node
-docker run -v ~/vermeer-config:/go/bin/config hugegraph/vermeer --env=master
+# Master node (with Web UI enabled)
+docker run -v ~/vermeer-config:/go/bin/config hugegraph/vermeer --env=master
-auth token -auth_token_factor 1234
# Worker node
docker run -v ~/vermeer-config:/go/bin/config hugegraph/vermeer --env=worker
@@ -158,6 +163,7 @@ Configure parameters in `vermeer.sh`, then:
#### Prerequisites
- Go 1.23 or later
+- Node.js/npm (for downloading UI assets)
- `curl` and `unzip` utilities (for downloading dependencies)
- Internet connection (for first-time setup)
@@ -226,10 +232,41 @@ task_strategy = 1
# Number of parallel tasks
task_parallel_num = 1
+
+# Authentication mode (none or token)
+# Set to "token" to enable Web UI and API authentication
+auth = none
+
+# Token authentication factor (required when auth=token)
+auth_token_factor = 1234
```
**Note**: HugeGraph connection details (`pd_peers`, `server`, `graph`) are
provided in the graph load API request, not in the configuration file. See
[HugeGraph Integration](#hugegraph-integration) section for details.
+### Generating Auth Token
+
+When `auth=token` is enabled, you need to generate a token for login. Use the
built-in token generator:
+
+```bash
+# Run with Go
+go run tools/token/token_generator.go -user admin -space default -factor 1234
-i
+
+# Or run in Docker (no local Go required)
+docker run --rm -v $(pwd):/src -v $(pwd)/config:/src/config golang:1.23-alpine
sh -c "cd /src && go run tools/token/token_generator.go -user admin -space
default -factor 1234 -i"
+```
+
+Parameters:
+- `-user` — Username (default: `foo`)
+- `-space` — Graph space name (default: `bar`)
+- `-factor` — Must match `auth_token_factor` in `master.ini`
+- `-client` — Client identifier (default: `hg`)
+- `-i` — Generate immortal token (never expires)
+
+The generated token can be used in two ways:
+
+1. **HTTP Header**: `Authorization: Bearer <token>`
+2. **Login API**: `POST /api/v1/login` with body `{"token": "<token>"}` (sets
cookie)
+
### Worker Configuration (`worker.ini`)
```ini
@@ -278,6 +315,8 @@ worker_group = default
Vermeer exposes a REST API on port `6688` (configurable in `master.ini`).
+> **Note**: The Web UI (`/ui/*`) is only available when `auth=token` is
configured. Set `auth_token_factor` in `master.ini` or pass `-auth token
-auth_token_factor <value>` via command line.
+
### Key Endpoints
| Endpoint | Method | Description |
@@ -502,7 +541,9 @@ vermeer/tools/protoc/linux64/protoc
vermeer/apps/protos/*.proto --go-grpc_out=ve
## Monitoring
-Access the Web UI dashboard at `http://master-ip:6688/ui/` for:
+Access the Web UI dashboard at `http://master-ip:6688/ui/master.html` for:
+
+> **Note**: The Web UI requires `auth=token` in `master.ini` (or `-auth token`
via command line). Without token authentication, the UI routes are not
registered.
- Worker status and resource usage
- Active and completed tasks
diff --git a/vermeer/asset/asset.go b/vermeer/asset/asset.go
index a2f15891..040a4361 100644
--- a/vermeer/asset/asset.go
+++ b/vermeer/asset/asset.go
@@ -25,4 +25,4 @@ import (
)
// Assets contains the project's assets.
-var Assets http.FileSystem = http.Dir("../ui")
+var Assets http.FileSystem = http.Dir("../ui/ui")
diff --git a/vermeer/asset/asset_dev_ui.go b/vermeer/asset/asset_dev_ui.go
index 1b82cab5..60a0b3a6 100644
--- a/vermeer/asset/asset_dev_ui.go
+++ b/vermeer/asset/asset_dev_ui.go
@@ -27,5 +27,5 @@ import (
func init() {
// for ui development
- Assets = http.Dir(common.AppRootPath() + "/ui/")
+ Assets = http.Dir(common.AppRootPath() + "/ui/ui/")
}
diff --git a/vermeer/build.sh b/vermeer/build.sh
index 47cd42e3..7d28846a 100644
--- a/vermeer/build.sh
+++ b/vermeer/build.sh
@@ -33,17 +33,21 @@ go mod download
echo "Checking binary dependencies..."
./scripts/download_binaries.sh
-# Generate assets if not exist
-if [ ! -f "asset/assets_vfsdata.go" ]; then
- echo "Generating assets..."
- cd asset && go generate && cd ..
+# Download UI assets if stamp file is missing
+echo "Checking UI assets..."
+if [ ! -f "ui/ui/lib/.downloaded" ]; then
+ ./scripts/download_ui_assets.sh
fi
+
+# Always regenerate embedded assets so UI source changes are picked up
+echo "Generating assets..."
+cd asset && go generate && cd ..
ARCH=$1
CGO_ENABLED=0 GOOS=linux GOARCH="$ARCH" go build
VERSION=$(cat ./apps/version/version.go | grep 'Version' | awk -F '"' '{print
$2}')
cp tools/supervisord/linux_"$ARCH"/supervisord supervisord
-tar --exclude=config/afs_client.conf -zcvf vermeer-"$VERSION"-"$ARCH".tar.gz
vermeer config/ supervisord vermeer.sh mem_supervisor.sh
+tar --exclude=config/afs_client.conf -zcvf vermeer-"$VERSION"-"$ARCH".tar.gz
vermeer config/ supervisord vermeer.sh mem_supervisor.sh release-docs/LICENSE
release-docs/NOTICE release-docs/licenses/
mkdir "$BUILD_REPO_WS"/output
mv vermeer-"$VERSION"-"$ARCH".tar.gz "$BUILD_REPO_WS"/output/
diff --git a/vermeer/config/worker.ini b/vermeer/config/worker.ini
index c11cbc4a..5bfd38b4 100644
--- a/vermeer/config/worker.ini
+++ b/vermeer/config/worker.ini
@@ -12,7 +12,6 @@
; 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.
-
[default]
log_level=info
debug_mode=release
@@ -20,4 +19,6 @@ http_peer=0.0.0.0:6788
grpc_peer=0.0.0.0:6789
master_peer=127.0.0.1:6689
run_mode=worker
-worker_group=default
\ No newline at end of file
+worker_group=default
+auth=none
+auth_token_factor=1234
diff --git a/vermeer/release-docs/LICENSE b/vermeer/release-docs/LICENSE
new file mode 100644
index 00000000..bb3cfbe1
--- /dev/null
+++ b/vermeer/release-docs/LICENSE
@@ -0,0 +1,244 @@
+ 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 [yyyy] [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.
+
+
+
+============================================================================
+ APACHE HUGEGRAPH SUBCOMPONENTS:
+
+ The Apache HugeGraph project contains subcomponents with separate copyright
+ notices and license terms. Your use of the source code for the these
+ subcomponents is subject to the terms and conditions of the following
+ licenses.
+
+========================================================================
+Third party MIT licenses
+========================================================================
+
+The following components are provided under the MIT License.
+See licenses/ for text of these licenses.
+
+ (The MIT License) * jQuery(jQuery:3.5.1-https://jquery.com/ )
+ (The MIT License) * Bootstrap(bootstrap:4.3.1-https://getbootstrap.com/ )
+ (The MIT License) * Bootstrap 3 Glyphicons
CSS(bootstrap-glyphicons:3.3.7-https://getbootstrap.com/ )
+ (The MIT License) * Font Awesome 5 Free
CSS(fontawesome-free:5.x-https://fontawesome.com/ )
+ (The MIT License) * Glyphicons Halflings
Font(glyphicons-halflings-regular-https://glyphicons.com/ )
+
+========================================================================
+Third party Apache 2.0 licenses
+========================================================================
+
+The following components are provided under the Apache 2.0 License.
+See licenses/ for text of these licenses.
+
+ (Apache License, Version 2.0) *
bootstrap4-glyphicons(bootstrap4-glyphicons-https://github.com/Darkseal/bootstrap4-glyphicons
)
+
+========================================================================
+Third party SIL Open Font licenses
+========================================================================
+
+The following components are provided under the SIL Open Font License 1.1.
+See licenses/ for text of these licenses.
+
+ (SIL OFL 1.1) * Font Awesome 5 Free
Fonts(fontawesome-free-fonts:5.x-https://fontawesome.com/ )
+ Font Awesome font files (fa-brands-400, fa-regular-400, fa-solid-900)
+ in eot, svg, ttf, woff, woff2 formats.
diff --git a/vermeer/release-docs/NOTICE b/vermeer/release-docs/NOTICE
new file mode 100644
index 00000000..6e8895d9
--- /dev/null
+++ b/vermeer/release-docs/NOTICE
@@ -0,0 +1,44 @@
+Apache HugeGraph - Vermeer
+Copyright 2022-2026 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+The initial codebase was donated to the ASF by HugeGraph Authors, copyright
2017-2021.
+
+========================================================================
+This product bundles the following third-party frontend assets:
+========================================================================
+
+jQuery 3.5.1
+ Copyright JS Foundation and other contributors
+ https://jquery.com/
+ Licensed under the MIT License
+
+Bootstrap 4.3.1
+ Copyright 2011-2019 Twitter, Inc.
+ Copyright 2011-2019 The Bootstrap Authors
+ https://getbootstrap.com/
+ Licensed under the MIT License
+
+bootstrap4-glyphicons
+ Copyright 2018 Darkseal / Ryadel
+ https://github.com/Darkseal/bootstrap4-glyphicons
+ Licensed under the Apache License, Version 2.0
+
+Bootstrap 3 Glyphicons CSS (bundled within bootstrap4-glyphicons)
+ Copyright 2011-2018 Twitter, Inc.
+ https://getbootstrap.com/
+ Licensed under the MIT License
+
+Font Awesome 5 Free (fonts and CSS bundled within bootstrap4-glyphicons)
+ Copyright 2018 Fonticons, Inc.
+ https://fontawesome.com/
+ Font files licensed under the SIL Open Font License 1.1
+ CSS and Less files licensed under the MIT License
+ Icons licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
+
+Glyphicons Halflings font files (bundled within bootstrap4-glyphicons)
+ Copyright 2011-2018 Twitter, Inc.
+ https://glyphicons.com/
+ Licensed under the MIT License
diff --git a/vermeer/release-docs/licenses/LICENSE-bootstrap.txt
b/vermeer/release-docs/licenses/LICENSE-bootstrap.txt
new file mode 100644
index 00000000..dee7c9d4
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-bootstrap.txt
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2011-2019 Twitter, Inc.
+Copyright (c) 2011-2019 The Bootstrap Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vermeer/release-docs/licenses/LICENSE-bootstrap4-glyphicons.txt
b/vermeer/release-docs/licenses/LICENSE-bootstrap4-glyphicons.txt
new file mode 100644
index 00000000..94e912e6
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-bootstrap4-glyphicons.txt
@@ -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 2018 Darkseal / Ryadel
+
+ 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/vermeer/release-docs/licenses/LICENSE-fontawesome.txt
b/vermeer/release-docs/licenses/LICENSE-fontawesome.txt
new file mode 100644
index 00000000..adbe7017
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-fontawesome.txt
@@ -0,0 +1,110 @@
+Font Awesome Free License
+-------------------------
+
+Font Awesome Free is free, open source, and GPL friendly. You can use it for
+commercial projects, open source projects, or really almost whatever you want.
+
+Icons -- CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
+In the Font Awesome Free download, the CC BY 4.0 license applies to all icons
+packaged as SVG and JS file types.
+
+Fonts -- SIL OFL 1.1 License (https://scripts.sil.org/OFL)
+In the Font Awesome Free download, the SIL OFL 1.1 license applies to all icons
+packaged as web and desktop font files.
+
+Code -- MIT License (https://opensource.org/licenses/MIT)
+In the Font Awesome Free download, the MIT license applies to all non-font and
+non-icon files.
+
+Attribution is required by MIT, SIL OFL 1.1, and CC BY 4.0 licenses. Based on
+the Font Awesome Free package, we have included attribution in the NOTICE file.
+
+Copyright 2018 Fonticons, Inc. (https://fontawesome.com)
+
+
+------------------------------------------------------------------------------
+SIL Open Font License 1.1
+------------------------------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components
+as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/vermeer/release-docs/licenses/LICENSE-glyphicons.txt
b/vermeer/release-docs/licenses/LICENSE-glyphicons.txt
new file mode 100644
index 00000000..74775809
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-glyphicons.txt
@@ -0,0 +1,26 @@
+MIT License (Glyphicons Halflings)
+
+Copyright 2011-2018 Twitter, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Note: Glyphicons Halflings font files were originally part of Bootstrap 3
+and are distributed under the MIT License by Twitter, Inc. The Glyphicons
+project (https://glyphicons.com/) provides the Halflings set for use with
+Bootstrap.
diff --git a/vermeer/release-docs/licenses/LICENSE-jquery.txt
b/vermeer/release-docs/licenses/LICENSE-jquery.txt
new file mode 100644
index 00000000..1730e965
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-jquery.txt
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright JS Foundation and other contributors, https://js.foundation/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vermeer/scripts/download_ui_assets.sh
b/vermeer/scripts/download_ui_assets.sh
new file mode 100755
index 00000000..ab78877f
--- /dev/null
+++ b/vermeer/scripts/download_ui_assets.sh
@@ -0,0 +1,177 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+
+set -e
+set -o pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
+UI_DIR="$PROJECT_ROOT/ui"
+LIB_DIR="$PROJECT_ROOT/ui/ui/lib"
+
+# Glyphicons source (GitHub raw) - pinned to specific commit for reproducible
builds
+GLYPHICONS_COMMIT="f7b1a17bbe64308d1d8b2b4bb2ba8a0ea621b377"
+GLYPHICONS_BASE="https://raw.githubusercontent.com/Darkseal/bootstrap4-glyphicons/${GLYPHICONS_COMMIT}/bootstrap4-glyphicons"
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m'
+
+log_info() {
+ echo -e "${GREEN}[INFO]${NC} $1"
+}
+
+log_warn() {
+ echo -e "${YELLOW}[WARN]${NC} $1"
+}
+
+log_error() {
+ echo -e "${RED}[ERROR]${NC} $1"
+}
+
+# Download a single file from URL to target path
+download_file() {
+ local url=$1
+ local target=$2
+
+ mkdir -p "$(dirname "$target")"
+ if ! curl -sL -f "$url" -o "$target"; then
+ log_error "Failed to download: $url"
+ return 1
+ fi
+}
+
+# Main function
+main() {
+ log_info "Downloading UI assets..."
+
+ # Check npm and node
+ if ! command -v npm &> /dev/null; then
+ log_error "npm is required but not installed. Please install
Node.js/npm first."
+ exit 1
+ fi
+ if ! command -v node &> /dev/null; then
+ log_error "node is required but not installed. Please install Node.js
first."
+ exit 1
+ fi
+
+ # Step 1: npm install (jQuery + Bootstrap)
+ log_info "Installing npm dependencies (jQuery, Bootstrap)..."
+ cd "$UI_DIR"
+ npm install --no-audit --no-fund
+ cd "$PROJECT_ROOT"
+
+ # Read actual versions from package.json (source of truth)
+ JQUERY_VERSION=$(node -p
"require('$UI_DIR/package.json').dependencies.jquery")
+ BOOTSTRAP_VERSION=$(node -p
"require('$UI_DIR/package.json').dependencies.bootstrap")
+
+ # Step 2: Create lib directory structure
+ log_info "Copying files to ui/ui/lib/..."
+ mkdir -p "$LIB_DIR"
+
+ # Copy jQuery (npm names it jquery.min.js, rename to match version)
+ cp "$UI_DIR/node_modules/jquery/dist/jquery.min.js"
"$LIB_DIR/jquery-${JQUERY_VERSION}.min.js"
+
+ # Copy Bootstrap CSS
+ mkdir -p "$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css"
+ cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap.min.css"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+ cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap.min.css.map"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+ cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap-grid.min.css"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+ cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap-grid.min.css.map"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+ cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap-reboot.min.css"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+ cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap-reboot.min.css.map"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+
+ # Copy Bootstrap JS
+ mkdir -p "$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js"
+ cp "$UI_DIR/node_modules/bootstrap/dist/js/bootstrap.min.js"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js/"
+ cp "$UI_DIR/node_modules/bootstrap/dist/js/bootstrap.min.js.map"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js/"
+ cp "$UI_DIR/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js/"
+ cp "$UI_DIR/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js.map"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js/"
+
+ # Copy Bootstrap LICENSE
+ cp "$UI_DIR/node_modules/bootstrap/LICENSE"
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/"
+
+ # Create jquery-license (MIT)
+ cat > "$LIB_DIR/jquery-license" << 'JQLICENSE'
+Copyright JS Foundation and other contributors, https://js.foundation/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+JQLICENSE
+
+ # Step 3: Download Bootstrap4 Glyphicons from GitHub
+ log_info "Downloading Bootstrap4 Glyphicons from GitHub..."
+ download_file "$GLYPHICONS_BASE/css/bootstrap-glyphicons.min.css" \
+ "$LIB_DIR/bootstrap4-glyphicons/css/bootstrap-glyphicons.min.css"
+
+ # Download fontawesome fonts
+ for font in fa-brands-400 fa-regular-400 fa-solid-900; do
+ for ext in eot svg ttf woff woff2; do
+ download_file "$GLYPHICONS_BASE/fonts/fontawesome/${font}.${ext}" \
+
"$LIB_DIR/bootstrap4-glyphicons/fonts/fontawesome/${font}.${ext}"
+ done
+ done
+
+ # Download glyphicons fonts
+ for ext in eot svg ttf woff woff2; do
+ download_file
"$GLYPHICONS_BASE/fonts/glyphicons/glyphicons-halflings-regular.${ext}" \
+
"$LIB_DIR/bootstrap4-glyphicons/fonts/glyphicons/glyphicons-halflings-regular.${ext}"
+ done
+
+ # Download maps
+ download_file "$GLYPHICONS_BASE/maps/glyphicons-fontawesome.less" \
+ "$LIB_DIR/bootstrap4-glyphicons/maps/glyphicons-fontawesome.less"
+ download_file "$GLYPHICONS_BASE/maps/glyphicons-fontawesome.min.css" \
+ "$LIB_DIR/bootstrap4-glyphicons/maps/glyphicons-fontawesome.min.css"
+
+ # Download bootstrap4-glyphicons LICENSE for release metadata
+
GLYPHICONS_LICENSE_URL="https://raw.githubusercontent.com/Darkseal/bootstrap4-glyphicons/${GLYPHICONS_COMMIT}/LICENSE"
+ if ! curl -sL -f "$GLYPHICONS_LICENSE_URL" -o
"$LIB_DIR/bootstrap4-glyphicons/LICENSE" 2>/dev/null; then
+ log_warn "Could not download bootstrap4-glyphicons LICENSE file (repo
may not have one)"
+ fi
+
+ # Stamp file for incremental builds
+ touch "$LIB_DIR/.downloaded"
+
+ log_info "All UI assets downloaded successfully!"
+ log_info ""
+ log_info "Downloaded to: $LIB_DIR"
+ log_info " - jQuery ${JQUERY_VERSION}"
+ log_info " - Bootstrap ${BOOTSTRAP_VERSION} (CSS + JS + source maps)"
+ log_info " - Bootstrap4 Glyphicons (CSS + fonts + maps)"
+}
+
+main "$@"
diff --git a/vermeer/ui/package.json b/vermeer/ui/package.json
new file mode 100644
index 00000000..978c95d8
--- /dev/null
+++ b/vermeer/ui/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "vermeer-ui",
+ "version": "1.0.0",
+ "private": true,
+ "description": "Frontend dependencies for Vermeer UI (downloaded at build
time for ASF compliance)",
+ "dependencies": {
+ "jquery": "3.5.1",
+ "bootstrap": "4.3.1"
+ }
+}
diff --git a/vermeer/ui/ui/lib/functions.js b/vermeer/ui/ui/lib/functions.js
new file mode 100644
index 00000000..faf73618
--- /dev/null
+++ b/vermeer/ui/ui/lib/functions.js
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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.
+ */
+; (function () {
+ const API_PREFIX = '/api/v1';
+ window.vermeer = {
+ login: function () {
+ const token = $('#admin_token').val();
+ if (!token) {
+ showDelModal('empty token');
+ return;
+ }
+
+ const req = { token: token };
+ postJson('/login', req,
+ function (data) {
+ console.log(data.message);
+ location.reload(true);
+ }
+ );
+ },
+ queryGraphs: function () {
+ const $t = $('#graphs_table');
+ $t.empty();
+ const fields = ['space_name', 'name', 'status', 'state',
'create_time',
+ 'update_time', 'use_out_edges', 'use_out_degree'];
+ $t.append('<thead><tr/></thead>');
+ const $tr = $t.find('thead tr');
+ $.each(fields, function (index, field) {
+ $tr.append($('<th/>').text(field));
+ });
+
+ const ok = function (data) {
+ const $tb = $('<tbody/>');
+ $t.append($tb);
+ const rows = data.graphs;
+ $.each(rows, function (index, row) {
+ $tb.append(toTableRow(fields, row));
+ });
+ };
+
+ get('/graphs', ok);
+ },
+ queryTasks: function () {
+ const $t = $('#tasks_table');
+ $t.empty();
+ const fields = ['id', 'space_name', 'graph_name', 'create_user',
'task_type',
+ 'status', 'state', 'create_time', 'start_time', 'update_time'];
+ $t.append('<thead><tr/></thead>');
+ const $tr = $t.find('thead tr');
+ $.each(fields, function (index, field) {
+ $tr.append($('<th/>').text(field));
+ });
+
+ const ok = function (data) {
+ const $tb = $('<tbody/>');
+ $t.append($tb);
+ const rows = data.tasks;
+ $.each(rows, function (index, row) {
+ $tb.append(toTableRow(fields, row));
+ });
+ };
+ get('/tasks', ok);
+ }
+
+ };
+
+ function toTableRow(fields, row) {
+ const $row = $('<tr>');
+ $.each(fields, function (index, field) {
+ let value = '';
+
+ if (field.endsWith('_time')) {
+ value = formatDate(row[field]);
+ } else {
+ value = row[field];
+ }
+
+ const $span = $('<span/>').text(value);
+
+ switch (value) {
+ case 'error':
+ $span.addClass('badge badge-lg badge-danger');
+ break;
+ case 'incomplete':
+ $span.addClass('badge badge-lg badge-warning');
+ break;
+ case 'complete':
+ case 'loaded':
+ case 'disk':
+ $span.addClass('badge badge-lg badge-success');
+ }
+
+ const $td = $('<td>').append($span);
+ $row.append($td);
+ });
+ return $row;
+ }
+
+ function showDelModal(text) {
+ $('#msg-modal-msg').text(text);
+ $('#msg-modal').modal('show');
+ }
+
+ function get(url, ok, error, caller) {
+ ajax('GET', url, '', ok, error, caller);
+ }
+
+ function postJson(url, data, ok, error, caller) {
+ ajax('POST', url, JSON.stringify(data), ok, error, caller);
+ }
+
+ function ajax(method, url, data, ok, error, caller) {
+ $.ajax({
+ url: API_PREFIX + url,
+ type: method,
+ data: data,
+ contentType: 'application/json',
+ success: function (response) {
+ if (!ok) {
+ console.log('ajax request successful:', response);
+ return;
+ }
+ if (caller) {
+ ok.apply(caller, [response]);
+ } else {
+ ok(response);
+ }
+ },
+ error: function (err) {
+ if (err.status === 401) {
+ showDelModal('Login First!');
+ return;
+ } else {
+ console.log('ajax request failed:', err);
+ }
+ if (!error) {
+ let data = JSON.parse(err.responseText);
+ showDelModal(data.message);
+ return;
+ }
+ if (caller) {
+ error.apply(caller, [err]);
+ } else {
+ error(err);
+ }
+ }
+ });
+ }
+
+ function formatDate(inputDate) {
+ if (!inputDate) {
+ return '-';
+ }
+ const date = new Date(inputDate);
+ if (isNaN(date.getTime()) || date.getFullYear() === 1) {
+ return '-';
+ }
+ const year = date.getFullYear();
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
+ const day = date.getDate().toString().padStart(2, '0');
+ const hours = date.getHours().toString().padStart(2, '0');
+ const minutes = date.getMinutes().toString().padStart(2, '0');
+ const seconds = date.getSeconds().toString().padStart(2, '0');
+
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+ }
+
+})();
+
+$(function () {
+ vermeer.queryGraphs();
+ vermeer.queryTasks();
+});
diff --git a/vermeer/ui/ui/lib/vermeer.css b/vermeer/ui/ui/lib/vermeer.css
new file mode 100644
index 00000000..a35ba7ef
--- /dev/null
+++ b/vermeer/ui/ui/lib/vermeer.css
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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.
+ */
+/* Move down content because we have a fixed navbar that is 50px tall with
20px padding */
+body {
+ padding-top: 70px;
+ padding-bottom: 20px;
+}
+
+.state_indicator {
+ padding: 0 4px 0 4px;
+}
+
+.literal_output td {
+ font-family: monospace;
+}
+
+.cursor-pointer {
+ cursor: pointer;
+}
+
+.tooltip-inner {
+ max-width: none;
+ text-align: left;
+}
+
+.label {
+ white-space: normal;
+}
+
+/* The navbar adds horizontal padding already */
+.navbar .container-fluid {
+ padding: 0;
+}
+
+/* This class provides style for containers that hold card like (without
background) objects within container-fluid and out of accordion */
+.blank-card {
+ padding-bottom: 50px;
+ padding-right: 25px;
+}
\ No newline at end of file