This is an automated email from the ASF dual-hosted git repository.
wu-sheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git
The following commit(s) were added to refs/heads/main by this push:
new fc6d9d5 docs: accuracy pass + concept-first config docs + principles;
release tooling (#38)
fc6d9d5 is described below
commit fc6d9d5b5233dc424dc878444f4459bd3a31edb0
Author: 吴晟 Wu Sheng <[email protected]>
AuthorDate: Tue Jun 2 10:44:50 2026 +0800
docs: accuracy pass + concept-first config docs + principles; release
tooling (#38)
Bring the website docs in line with the current code after the 0.6.0 work,
restructure the config docs around the UI (JSON as reference), codify the
doc-writing principles, and make the post-vote finalize script Docker-Hub
verify-only. CHANGELOG updated under 0.7.0.
Staleness fixes
- access-control/rbac.md + setup/rbac.md: document the `infra-3d:read` verb.
- access-control/admin-pages.md: add `/admin/3d-map` (`overview:write`).
- access-control/audit-log.md: rewrite the recorded-actions table to the
actually-emitted actions; drop the never-emitted rows; fix the failure
outcome format (`http_<code>`).
- operate/inspect.md: correct the BFF routes to `/api/inspect/*`.
- design-target.md: add the Topology overview widget.
- customization/layer-templates.md: fix the components example to the real
flag keys; add the `dependency` dashboard scope.
- operate/infra-3d-map.md: rewrite Configuration for the redesigned model;
add the Hierarchy pipeline stage.
Config docs are concept-first
- infra-3d-map / layer-templates / overview-templates lead with the concept
and the admin UI; the JSON shape is a reference appendix. No raw-JSON
editor exists on these pages, so the docs no longer imply one.
Versioning
- Docs no longer hardcode the Horizon version (the website pins docs per
release); container-image.md stays as the release-tooling exception.
i18n
- i18n.md: language x scope coverage matrix.
- adding-a-new-layer.md: add the "Add translations (i18n)" contributor step.
docs/CLAUDE.md (new)
- Operator-first, config-UI-first with JSON-as-appendix, no hardcoded
versions, plus a carve-out for contributor pages.
Release tooling
- release-finalize.sh: the Docker Hub image is published by CI on `v*` tags;
Step 5 now verifies the published tags, and the manual local-push fallback
plus Docker Hub login preflight were removed.
---
CHANGELOG.md | 15 +++++-
docs/CLAUDE.md | 71 +++++++++++++++++++++++++++
docs/access-control/admin-pages.md | 1 +
docs/access-control/audit-log.md | 24 ++++-----
docs/access-control/rbac.md | 3 +-
docs/customization/adding-a-new-layer.md | 21 +++++++-
docs/customization/i18n.md | 17 +++++++
docs/customization/layer-templates.md | 25 ++++++----
docs/customization/overview-templates.md | 8 +--
docs/design-target.md | 1 +
docs/operate/infra-3d-map.md | 73 ++++++++++++++++------------
docs/operate/inspect.md | 4 +-
docs/setup/overview.md | 8 +--
docs/setup/rbac.md | 2 +-
scripts/release-finalize.sh | 83 +++++++++-----------------------
15 files changed, 229 insertions(+), 127 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35509be..921875a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,20 @@ packages) plus the BFF's `HORIZON_VERSION` default.
## 0.7.0
-(In development — fill in highlights here before cutting the release.)
+### Documentation & release tooling
+
+- The website docs were brought current with the 0.6.0 build and the
+ configuration pages restructured around the admin UI — the JSON shape is
+ now a reference appendix, not an authoring surface (these admin pages are
+ structured editors, not raw-JSON editors). Accuracy fixes span the RBAC
+ verbs (incl. `infra-3d:read`), the audit-log action set, the Metrics
+ Inspect API paths, the layer-template component flags, and the redesigned
+ 3D-map config + loading stages. A new `docs/CLAUDE.md` records the
+ doc-writing principles, and the i18n docs gain a language × scope coverage
+ matrix plus a translation step in the add-a-layer recipe.
+- The container image is published to Docker Hub by CI on every `v*` tag;
+ the post-vote finalize script now only verifies the published tags (the
+ manual local-push fallback and Docker Hub login preflight were removed).
## 0.6.0
diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md
new file mode 100644
index 0000000..bb5c5a6
--- /dev/null
+++ b/docs/CLAUDE.md
@@ -0,0 +1,71 @@
+# CLAUDE.md — Writing the Horizon UI docs
+
+`docs/` is the **public website documentation** for Horizon UI — a flat tree,
+ordered by `menu.yml`, synced to the Apache SkyWalking website. It is written
+for the people who **run and configure** Horizon (operators, dashboard
+authors), not for contributors hacking on the code. These are the principles
+for every page here. For the project-wide rules, see the root
+[CLAUDE.md](../CLAUDE.md).
+
+## 1. Operator perspective first
+
+Document what a feature **does**, how to **configure** it, and how to
+**operate / troubleshoot** it — observable behavior and configuration.
+
+Do **not** document the internals:
+
+- no source-file paths (`apps/bff/src/…`, `apps/ui/src/…`),
+- no internal function / composable / store / route-handler names,
+- no implementation narration ("the BFF then chunks / fans out / probes …"),
+- no step-by-step retelling of the code's algorithm.
+
+If a sentence only makes sense to someone reading the source, it does not
+belong in a doc.
+
+**One carve-out: contributor pages.** A few pages document repo / file-based
+authoring that has no UI path — adding a new layer template, contributing a
+translation catalog or a new locale. These are explicitly contributor-facing
+and may reference repo files, `pnpm` commands, and the dev workflow; keep them
+scoped to that task. Today: `customization/adding-a-new-layer.md` and the
+contributor sections of `customization/i18n.md`. Everything else stays
+operator-facing.
+
+## 2. Config is edited in the UI — lead with that; JSON is an appendix
+
+Almost everything configurable in Horizon (layer dashboards, overview
+templates, the 3D-map config, alarm-page setup, global defaults, translations)
+is edited through a **structured / visual admin page**, on a bundled default →
+local draft → **Check diff & push** to OAP flow. A configuration page should:
+
+- **Start from the concept** — what this configuration is and what it controls.
+- **Then the UI** — which admin page edits it and what the controls do.
+- **Keep the JSON / schema as a reference appendix** at the end, framed as the
+ *stored* format the editor reads and writes (useful for understanding the
+ fields, or authoring as files), **not** as the primary "how to author" path.
+
+There is **no raw-JSON editor on these pages.** Never tell the reader to "edit
+the JSON" on a page — they use the structured controls. The Monaco view that
+appears is a read-only **diff** for review before pushing.
+
+## 3. Don't hardcode the Horizon version
+
+The website serves these docs **pinned per release**, so a version string in
+the body is redundant and silently goes stale on the next release. By default,
+write version-neutral: use a `<version>` placeholder in install commands, or
+phrase around it. State a concrete version only when the content is genuinely
+version-specific (a compatibility note, or a "new in X" call-out you
+deliberately want pinned).
+
+The **one maintained exception** is `setup/container-image.md`: its image tags
+track the current release and are advanced automatically by the release tooling
+— leave them as concrete versions.
+
+## 4. Other house rules
+
+- **Tech terms and proper nouns stay verbatim** — SkyWalking, OAP, MQE, eBPF,
+ Kubernetes, Istio, GraphQL, layer keys (`GENERAL`, `MESH`), scope enums
+ (Service, Endpoint), metric ids. Don't translate or rename them.
+- **Cross-link, don't duplicate.** One canonical page per concept; link to it
+ rather than restating it.
+- **Add new pages to `menu.yml`.** A page that isn't in the menu isn't
+ navigable on the site.
diff --git a/docs/access-control/admin-pages.md
b/docs/access-control/admin-pages.md
index 350c131..b8b1b41 100644
--- a/docs/access-control/admin-pages.md
+++ b/docs/access-control/admin-pages.md
@@ -114,6 +114,7 @@ Read-only. To change roles, edit `rbac.roles` in
`horizon.yaml`; hot-reload appl
| `/operate/inspect` | `inspect:read` | maintainer, operator, admin |
| `/operate/ttl` | `ttl:read` | maintainer, operator, admin |
| `/operate/config` | `config:read` | maintainer, operator, admin |
+| `/admin/3d-map` | `overview:write` | operator, admin |
`auth:read`, `user:read`, `role:read` are **not** in any default role. Either
grant them via a custom role:
diff --git a/docs/access-control/audit-log.md b/docs/access-control/audit-log.md
index 125ab14..57008a2 100644
--- a/docs/access-control/audit-log.md
+++ b/docs/access-control/audit-log.md
@@ -10,10 +10,10 @@ Each event has these fields:
|---|---|
| `ts` | ISO-8601 timestamp. |
| `actor` | Username, or `null` for system events. |
-| `action` | Operation name, such as `auth.login` or `rule.addOrUpdate`. |
+| `action` | Operation name, such as `auth.login` or `addOrUpdate`. |
| `verb` | RBAC verb checked, when applicable. |
| `target` | Resource id or name, when applicable. |
-| `outcome` | `success`, `failure`, `break-glass`, or the upstream HTTP/OAP
status. |
+| `outcome` | `success` / `ok` / `break-glass` for normal flows; the OAP
`applyStatus` or `http_<code>` on an upstream failure. |
| `details` | Extra context for the operation. |
| `fromIp` | Requester IP. |
| `sessionId` | Session id, when a session exists. |
@@ -26,21 +26,22 @@ tail -f horizon-audit.jsonl | jq -c 'select(.action |
startswith("auth."))'
## Recorded actions
-The recorded set can grow between releases. In 0.5.0:
+The recorded set can grow between releases. The current set:
| Action | Outcome values | Notes |
|---|---|---|
| `auth.login` | `success`, `failure` | Standard login. `details.backend` is
`local` or `ldap`. On success `details.roles` carries the resolved role list. |
| `auth.login.break-glass` | `break-glass` | Emergency admin login. Logged in
addition to a WARN application log line. |
| `auth.logout` | `success` | Explicit logout (cookie cleared). Sessions that
simply expire are not logged. |
-| `rule.addOrUpdate` | `success`, HTTP status on failure | DSL Management
create / update. `target` is the rule name; `details` carries the diff summary.
|
-| `rule.delete` | `success`, HTTP status on failure | DSL Management delete. |
-| `alarm-rule.addOrUpdate` | `success`, HTTP status on failure | Alarm Rule
editor write. |
-| `setup.write` | `success`, HTTP status on failure | Per-user setup state
write. |
-| `overview-template.write` | `success` | Overview template admin edits. |
-| `layer-template.write` | `success` | Layer template admin edits. |
+| `addOrUpdate` | OAP `applyStatus`, or `http_<code>` on failure | DSL
Management — create / update a rule. `target` is the rule name;
`details.catalog` is the rule catalog (alarm, MAL, OAL, …). |
+| `inactivate` | OAP `applyStatus`, or `http_<code>` | DSL Management —
deactivate a rule. |
+| `delete` | OAP `applyStatus`, or `http_<code>` | DSL Management — delete a
rule. `details.mode` is the delete mode. |
+| `alarms.config.save` | `ok`, or an error status on failure | Alarm page
setup save. |
+| `setup.save` | `success`, or an error status on failure | Per-user setup
state write (service / instance / endpoint setup). |
+| `debug.start` | `ok`, or an error status on failure | Live Debugger — start
a session. |
+| `debug.stop` | `ok`, or an error status on failure | Live Debugger — stop a
session. |
-`outcome` is the literal string for normal flows (`success`, `failure`,
`break-glass`) and a stringified HTTP / OAP status code when the underlying
call failed. This makes audit-time error correlation straightforward: an entry
with `outcome: "503"` tells you OAP returned a server error.
+`outcome` is a short literal for normal flows (`success`, `ok`, or
`break-glass`) and, when the underlying OAP call fails, the OAP `applyStatus`
value or `http_<code>`. This makes audit-time error correlation
straightforward: an entry with `outcome: "http_503"` tells you OAP returned a
server error.
## Example entries
@@ -93,10 +94,11 @@ The recorded set can grow between releases. In 0.5.0:
{
"ts": "2026-05-18T15:02:11.004Z",
"actor": "alice",
- "action": "rule.addOrUpdate",
+ "action": "addOrUpdate",
"verb": "rule:write",
"target": "service_resp_time_rule",
"outcome": "success",
+ "details": { "catalog": "alarm" },
"fromIp": "10.0.5.12",
"sessionId": "k7r..."
}
diff --git a/docs/access-control/rbac.md b/docs/access-control/rbac.md
index 00e8963..0727d50 100644
--- a/docs/access-control/rbac.md
+++ b/docs/access-control/rbac.md
@@ -26,12 +26,13 @@ Known verbs are grouped into areas:
| `topology:read` | Topology tab, topology widgets on overviews. |
| `profile:read` | Profiling tab (results read-only). |
| `overview:read` | Public overview dashboards. |
+| `infra-3d:read` | 3D Infrastructure Map — the map's config + live traffic
metrics. |
### Operate — dashboards, rules, diagnostics
| Verb | Gates |
|---|---|
-| `overview:write` | Overview templates admin page
(`/admin/overview-templates`): edit. |
+| `overview:write` | Overview templates (`/admin/overview-templates`) and the
3D-map config (`/admin/3d-map`): edit / publish. |
| `dashboard:read` / `dashboard:write` | Layer dashboard templates admin page:
list / edit. |
| `alarm-setup:read` / `alarm-setup:write` | Alarm Setup page: list / edit. |
| `alarm-rule:read` / `alarm-rule:write` | Alarm Rule catalog: list / edit. |
diff --git a/docs/customization/adding-a-new-layer.md
b/docs/customization/adding-a-new-layer.md
index f600edc..2a06cd0 100644
--- a/docs/customization/adding-a-new-layer.md
+++ b/docs/customization/adding-a-new-layer.md
@@ -90,7 +90,23 @@ Bundled template changes need a BFF restart (templates are
loaded once at startu
Each iteration is template + BFF restart. The schema is validated at startup;
a bad template logs the error and falls back to defaults — check the BFF logs.
-### 9. Promote to admin-editable (optional)
+### 9. Add translations (i18n)
+
+The template's English strings — the layer `alias`, any `aliases.*`, `slots`,
and the widget titles / KPI labels / group titles / tooltips inside
`dashboards` — are the i18n source. Generate the sibling overlay catalogs so
the layer renders in every shipped language:
+
+```sh
+pnpm --filter @skywalking-horizon-ui/bff i18n:seed
+```
+
+This walks every bundled template and writes one
`<your-key>.i18n.<locale>.json` per non-English locale (`de`, `es`, `fr`, `ja`,
`ko`, `pt`, `zh-CN`), pre-filling shared widget vocabulary from the lexicon.
Existing translations are preserved — only gaps are added. Fill the
layer-specific prose you care about in each overlay (anything left blank falls
back to English at render), then check for drift:
+
+```sh
+pnpm --filter @skywalking-horizon-ui/bff i18n:validate
+```
+
+See [Languages and Translations](i18n.md) for the language × scope coverage,
the shared lexicon, and how to add a brand-new locale.
+
+### 10. Promote to admin-editable (optional)
Once the template stabilizes:
@@ -99,7 +115,7 @@ Once the template stabilizes:
The local bundled file remains the fallback. After you publish, the OAP-stored
template becomes the runtime copy every Horizon instance reads.
-### 10. Add an overview entry (optional)
+### 11. Add an overview entry (optional)
If the new layer belongs in a war-room view:
@@ -141,4 +157,5 @@ OAP-side rename means a new enum key. Horizon will see the
old key go inactive (
- [Layer Dashboard Templates](layer-templates.md) — field reference.
- [Menu Structure](menu-structure.md) — how the sidebar composes layers.
- [Overview Templates](overview-templates.md) — cross-layer dashboards.
+- [Languages and Translations](i18n.md) — translating the template's strings.
- [Components → Dashboard Widgets](../components/dashboard-widgets.md) —
widget primitive reference.
diff --git a/docs/customization/i18n.md b/docs/customization/i18n.md
index 520b4cc..0d728a4 100644
--- a/docs/customization/i18n.md
+++ b/docs/customization/i18n.md
@@ -21,6 +21,20 @@ in English first; the other locales are catalog overlays.
Missing keys
fall back to English at the leaf, never at the file — a half-translated
catalog renders strictly better than English-only.
+## Coverage by scope
+
+All eight languages are first-class across the surfaces Horizon controls. The
scope decides **where** the translation resolves:
+
+| Scope | Resolves | Languages |
+|---|---|---|
+| UI chrome — buttons, labels, modals, login, topbar, sidebar | In the browser
(vue-i18n) | All 8 |
+| Bundled layer-dashboard templates | On the BFF, from sibling overlay
catalogs | All 8 |
+| Bundled overview templates | On the BFF | All 8 |
+| User-maintained dashboards saved to OAP | On the BFF, from each dashboard's
embedded `i18n` block | English + whatever the author provides |
+| OAP-supplied data — service / instance / endpoint / alarm names, tags, log
lines, trace ops | not translated | rendered verbatim |
+
+A missing key in any translated scope falls back to English at the leaf, so a
partially-translated catalog renders better than English-only.
+
## Picking a language
The locale picker lives in the topbar (next to the theme chip) and on
@@ -124,3 +138,6 @@ pnpm --filter @skywalking-horizon-ui/bff i18n:validate
It rejects catalog keys that no longer match the source template,
non-string values at translatable paths, and lexicon entries that
aren't present in the source `en.json` lexicon registry.
+
+When you add a **new layer**, generating its template's translations is part
+of that workflow — see [Adding a New Layer](adding-a-new-layer.md).
diff --git a/docs/customization/layer-templates.md
b/docs/customization/layer-templates.md
index eb00a03..d35adb3 100644
--- a/docs/customization/layer-templates.md
+++ b/docs/customization/layer-templates.md
@@ -2,9 +2,9 @@
A **layer template** is a single JSON file that describes everything Horizon
needs to know about one OAP layer: its display name, color, sidebar grouping,
which sub-tabs to expose, the service-list picker columns, the per-scope widget
grids, the trace/log/topology routing, and the service-name parsing rule.
-There is **one template per layer**, stored under
`apps/bff/src/bundled_templates/layers/<key>.json` (lowercase filename matches
the OAP layer enum, e.g. `general.json` for the `GENERAL` layer).
+There is **one template per layer**. Horizon ships a bundled template for
every supported layer, and an administrator customizes them in the **Layer
Dashboards** admin page (under *Dashboard setup*) — a visual editor that saves
a local draft and publishes to OAP with **Check diff & push**. You don't
hand-edit JSON on the page; the shape documented below is the stored format the
editor reads and writes, useful for understanding what each control maps to and
for authoring templates as files.
-## Top-level shape
+## Template shape (reference)
```json
{
@@ -22,6 +22,7 @@ There is **one template per layer**, stored under
`apps/bff/src/bundled_template
"service": [ ... widgets ... ],
"instance": [ ... widgets ... ],
"endpoint": [ ... widgets ... ],
+ "dependency":[ ... widgets ... ],
"topology": [ ... widgets ... ],
"trace": [ ... widgets ... ],
"logs": [ ... widgets ... ],
@@ -83,17 +84,21 @@ Per-tab feature toggles. A `false` value hides the tab.
```json
"components": {
- "service": true,
- "instance": true,
- "endpoint": true,
- "topology": true,
- "trace": true,
- "logs": false,
- "profiling": true
+ "service": true,
+ "instances": true,
+ "endpoints": true,
+ "endpointDependency": true,
+ "topology": true,
+ "traces": true,
+ "logs": true,
+ "traceProfiling": true,
+ "ebpfProfiling": false,
+ "asyncProfiling": false,
+ "pprofProfiling": false
}
```
-The landing tab when a layer is clicked is the **first enabled** in the
priority order `service → instance → endpoint → topology → trace → logs →
profiling`.
+The keys are the per-layer sub-tabs. `networkProfiling` and `podLogs` are also
available; any key omitted defaults to enabled. The landing tab when a layer is
clicked is the **first enabled** in the priority order `service → instances →
endpoints → endpointDependency → topology → traces → logs → traceProfiling`.
## `header`
diff --git a/docs/customization/overview-templates.md
b/docs/customization/overview-templates.md
index 24a1cce..6e8be11 100644
--- a/docs/customization/overview-templates.md
+++ b/docs/customization/overview-templates.md
@@ -2,12 +2,12 @@
An **overview template** is a JSON file describing a war-room / cross-cutting
dashboard composed from MQE-driven widgets on a 12-column grid. Overviews are
independent of any single layer and are designed for the operator's "is
everything OK?" pane.
-Bundled templates: `apps/bff/src/bundled_templates/overviews/<id>.json`.
Examples:
+Horizon ships bundled overview templates, and an administrator customizes them
in the **Overview Templates** admin page (`/admin/overview-templates`, under
*Dashboard setup*) — a visual editor that saves a local draft and publishes to
OAP with **Check diff & push**. You don't hand-edit JSON on the page; the shape
documented below is the stored format the editor reads and writes. Bundled
examples:
-- `services.json` — cross-layer service health + Kubernetes capacity summary.
-- `mesh.json` — Istio data-plane services + pilot activity + Kubernetes.
+- **Service Health** — cross-layer service health + Kubernetes capacity
summary.
+- **Mesh** — Istio data-plane services + pilot activity + Kubernetes.
-## Top-level shape
+## Template shape (reference)
```json
{
diff --git a/docs/design-target.md b/docs/design-target.md
index 49fbf83..e9fed63 100644
--- a/docs/design-target.md
+++ b/docs/design-target.md
@@ -23,6 +23,7 @@ Horizon ships dedicated widget primitives for observability
stacks instead of ge
- **KpiTileWidget** — compound tile combining a service count with N KPI rows
(number or progress-bar style).
- **MetricCompositeWidget** — mixed-style KPI grid (e.g., Kubernetes cluster
summary: node count + CPU/memory progress bars).
- **AlarmsWidget** — read-only active-incident rail with a 60-minute window,
dual-mode (modern `queryAlarms` capability + legacy `getAlarm` fallback).
+- **Topology** — embedded service-map snapshot for the configured layer,
showing live services and call flows on an overview.
- **TimeChart** — multi-series line chart with dual y-axis, synced crosshairs
across all widgets on the same page.
- **TopList** — top-N sorted list with optional tab switcher for multiple
expressions.
- **AlarmsTimeline** — per-minute stacked bar with brush selection for triage.
diff --git a/docs/operate/infra-3d-map.md b/docs/operate/infra-3d-map.md
index cbac6aa..95f21d7 100644
--- a/docs/operate/infra-3d-map.md
+++ b/docs/operate/infra-3d-map.md
@@ -128,8 +128,12 @@ progress live:
1. **Services** — the service roster and which layers they belong to.
2. **Templates** — which layers carry a topology.
3. **Topologies** — each topology-bearing layer's call graph.
-4. **Layout** — placing the cubes.
-5. **Metrics** — the per-service traffic numbers, fetched in batches so
+4. **Hierarchy** — the cross-tier identity links between the different
+ views of the same service. Only services that are new since the last
+ run are fetched; the rest are reused, so a steady deployment costs
+ nothing here on refresh.
+5. **Layout** — placing the cubes.
+6. **Metrics** — the per-service traffic numbers, fetched in batches so
the cubes light up progressively.
Each step shows its status as the map builds; click a step to open a
@@ -139,33 +143,42 @@ strip re-runs the whole sequence.
## Configuration
-The map is driven by a global configuration that an administrator edits
-at `/admin/3d-map` (linked under **Dashboard setup** in the sidebar).
-The editor is the same dark, dense surface as the rest of Horizon's
-admin pages, with a structured form plus an advanced raw-JSON view.
-
-From it you can:
-
-- **Filter layers** — a global filter, plus a per-tier filter, to choose
- which layers appear on the map.
-- **Arrange tiers** — rename tiers, reorder them top-to-bottom, and
- assign each layer to a tier.
+What the map shows is driven by a single configuration that an
+administrator edits in the UI at `/admin/3d-map` (linked under
+**Dashboard setup** in the sidebar). It is a **structured editor** — you
+work with tiers, layers, colors, and metrics through form controls, not
+raw JSON. Horizon ships a bundled default so the map is useful out of the
+box; your edits are kept as a local draft in your browser, and **Check
+diff & push** publishes them to OAP — which is the copy the map then
+renders (falling back to the bundled default if OAP has none).
+
+From the editor you can:
+
+- **Filter layers** — one global layer filter, written as a regex. A
+ layer it excludes is dropped from the map entirely. This is the only
+ filter; everything it admits is then placed on a tier.
+- **Arrange tiers** — rename tiers, reorder them top-to-bottom, and pin
+ each layer to a tier. A layer you don't pin lands on the **failover
+ tier** you nominate, so nothing silently falls off the map.
+- **Group layers** — cluster several related layers (for example the
+ SkyWalking self-observability components) into one labelled block on a
+ tier, while each member keeps its own cube color.
- **Color layers** — pick each layer's brand color (used for the cube,
zone, and stamp).
-- **Choose traffic metrics** — pick the throughput metric and unit each
- layer's cubes display. Topology layers can carry both a server-side and
- client-side metric (the server side is preferred, with the client side
- as a fallback); other layers carry a single load metric. The bundled
- defaults are seeded from each layer's dashboard template, so most
- layers show a sensible number out of the box.
-- **Style connections** — adjust the color and weight of the in-layer,
- cross-layer, and hierarchy lines.
-
-Saving takes effect the next time the map is opened. A **Reset to
-bundled** action restores the shipped defaults for review before saving.
-
-The bundled configuration is the read-only baseline; saved changes
-shadow it. Both the map and the editor are gated by access control — any
-signed-in user with read access can view the map, while editing the
-configuration requires the 3D-map write permission (granted to operators
-and admins by default). See [Roles and Permissions](../access-control/rbac.md).
+- **Choose a traffic metric** — for each layer, set the single throughput
+ metric its cubes display: the MQE expression, a display label, and a
+ unit. The bundled defaults are seeded from each layer's dashboard
+ template, so most layers show a sensible number out of the box.
+
+A read-only **Service-map layers** list shows which layers lay their
+cubes out as a call graph — that comes from each layer's template (its
+service-map capability), not from this page.
+
+Pushed changes take effect the next time the map is opened. A **Reset**
+action reloads either the shipped bundled default or OAP's current
+version, so you can start over before saving.
+
+Viewing the map needs read access (`infra-3d:read`, held by the built-in
+viewer role and above); editing and publishing the configuration needs
+`overview:write` (operators and admins by default). See
+[Roles and Permissions](../access-control/rbac.md).
diff --git a/docs/operate/inspect.md b/docs/operate/inspect.md
index 5c9dd4d..6f374c7 100644
--- a/docs/operate/inspect.md
+++ b/docs/operate/inspect.md
@@ -24,7 +24,7 @@ If any of these is missing, the page surfaces a hint banner
directing the operat
## Catalog browser
-**Endpoint:** `GET
/inspect/metrics?regex=<pattern>&type=<type>&catalog=<catalog>&mqeQueryable=<bool>`
+**Endpoint:** `GET
/api/inspect/metrics?regex=<pattern>&type=<type>&catalog=<catalog>&mqeQueryable=<bool>`
Filters:
@@ -48,7 +48,7 @@ The list is virtualized — a typical OAP exposes hundreds of
metrics; scrolling
## Entity enumerator
-**Endpoint:** `GET
/inspect/entities?metric=<name>&start=<...>&end=<...>&step=<DAY|HOUR|MINUTE>&limit=<n>`
+**Endpoint:** `GET
/api/inspect/entities?metric=<name>&start=<...>&end=<...>&step=<DAY|HOUR|MINUTE>&limit=<n>`
For a chosen metric, OAP returns the set of entities that have data in the
window. Useful for:
diff --git a/docs/setup/overview.md b/docs/setup/overview.md
index 9abdae4..614de02 100644
--- a/docs/setup/overview.md
+++ b/docs/setup/overview.md
@@ -12,11 +12,11 @@ This page is the shortest path from "no Horizon" to
"Horizon in front of a runni
### 1. Unpack Horizon
-Unpack the binary tarball and copy the example config:
+Unpack the binary tarball (substitute the release version you downloaded for
`<version>`) and copy the example config:
```sh
-tar -xzf apache-skywalking-horizon-ui-0.5.0-bin.tar.gz
-cd apache-skywalking-horizon-ui-0.5.0-bin
+tar -xzf apache-skywalking-horizon-ui-<version>-bin.tar.gz
+cd apache-skywalking-horizon-ui-<version>-bin
cp horizon.example.yaml horizon.yaml
```
@@ -100,7 +100,7 @@ docker run -d --name horizon \
-p 8081:8081 \
-v "$PWD/horizon.yaml:/app/horizon.yaml:ro" \
-v horizon-state:/data \
- ghcr.io/apache/skywalking-horizon-ui:0.5.0
+ ghcr.io/apache/skywalking-horizon-ui:<version>
```
See [Container Image](container-image.md) for image tags, Kubernetes YAML, log
handling, and probes.
diff --git a/docs/setup/rbac.md b/docs/setup/rbac.md
index 963e83b..5120ad0 100644
--- a/docs/setup/rbac.md
+++ b/docs/setup/rbac.md
@@ -31,7 +31,7 @@ rbac:
| Role | Purpose | Grants |
|---|---|---|
-| `viewer` | Read-only data catalog and public overviews. | `metrics:read`,
`alarms:read`, `traces:read`, `logs:read`, `topology:read`, `profile:read`,
`overview:read`. Deliberately not `*:read` so the viewer cannot see rule
definitions, live-debug sessions, setup screens, or platform internals. |
+| `viewer` | Read-only data catalog and public overviews. | `metrics:read`,
`alarms:read`, `traces:read`, `logs:read`, `topology:read`, `profile:read`,
`overview:read`, `infra-3d:read`. Deliberately not `*:read` so the viewer
cannot see rule definitions, live-debug sessions, setup screens, or platform
internals. |
| `maintainer` | Viewer + platform monitoring. | viewer baseline +
`cluster:read`, `ttl:read`, `config:read`, `inspect:read`. |
| `operator` | Configures observability. | maintainer baseline +
`overview:write`, `setup:read/write`, `dashboard:read/write`,
`alarm-setup:read/write`, `alarm-rule:read/write`, `rule:*` (including
`rule:write:structural`, `rule:delete`, `rule:debug`), `live-debug:*`,
`profile:enable`. |
| `admin` | Unrestricted. | `*`. |
diff --git a/scripts/release-finalize.sh b/scripts/release-finalize.sh
index c160c00..e901818 100755
--- a/scripts/release-finalize.sh
+++ b/scripts/release-finalize.sh
@@ -39,16 +39,16 @@
# 3. Verify the Docker Hub multi-arch image — CI's publish-image
# workflow mirrors the GHCR image to Docker Hub automatically on
# every `v*` tag push (apache/skywalking-ui:horizon-<v> and
-# apache/skywalking-ui:latest). This step just confirms the two
-# expected tags are present. Falls back to a manual local mirror
-# (same `docker buildx imagetools create` CI runs) if CI didn't
-# publish — needs Docker Hub push rights on apache/skywalking-ui.
+# apache/skywalking-ui:latest). This step only CONFIRMS the two
+# expected tags are present; publishing is CI's job. There is no
+# local-push fallback — if the tags are missing, re-run the
+# publish-image workflow and re-run this script.
#
# Usage: bash scripts/release-finalize.sh
#
# The script is idempotent-ish and confirms before every irreversible step
-# (SVN move, SVN delete, gh release, each image push). Nothing destructive
-# happens without a y/N.
+# (SVN move, SVN delete, gh release). Nothing destructive happens without
+# a y/N. The Docker Hub image is published by CI, not here.
set -e -o pipefail
@@ -80,7 +80,7 @@ svn_exists() {
note "Step 1 — Tool + auth preflight"
MISSING=()
-for t in svn gh git docker shasum curl node; do
+for t in svn gh git docker shasum curl; do
command -v "$t" >/dev/null || MISSING+=("$t")
done
if [ ${#MISSING[@]} -gt 0 ]; then
@@ -89,8 +89,8 @@ if [ ${#MISSING[@]} -gt 0 ]; then
fi
if ! docker buildx version >/dev/null 2>&1; then
- err "docker buildx is required (Step 5 uses 'imagetools create' to copy"
- err "the CI-built multi-arch manifest from GHCR to Docker Hub)."
+ err "docker buildx is required (Step 5 uses 'imagetools inspect' to"
+ err "verify the CI-published Docker Hub tags)."
exit 1
fi
@@ -101,21 +101,6 @@ if ! gh auth status >/dev/null 2>&1; then
fi
echo "gh: $(gh auth status 2>&1 | grep -m1 'Logged in' | sed
's/^[[:space:]]*//')"
-# Docker Hub: confirm a stored login. The push itself will 403 if the
-# logged-in account lacks push rights to the apache org — surface the
-# identity now so a wrong account is caught before the long build.
-DOCKER_USER=$(printf 'https://index.docker.io/v1/' | docker-credential-desktop
get 2>/dev/null \
- | node -e "let
s='';process.stdin.on('data',d=>s+=d);process.stdin.on('end',()=>{try{process.stdout.write(JSON.parse(s).Username||'')}catch(e){}})"
2>/dev/null || true)
-if [ -z "${DOCKER_USER}" ]; then
- echo "Could not read a Docker Hub login from the credential store."
- echo "If you are not logged in, run: docker login"
- confirm "Continue anyway (the push will fail if not authorized)?" || {
echo "Aborted."; exit 1; }
-else
- echo "Docker Hub login: ${DOCKER_USER}"
- echo " NOTE: pushing to ${DOCKERHUB_REPO} needs this account to have push
rights"
- echo " in the 'apache' Docker Hub org. The push 403s otherwise."
-fi
-
# ========================== Step 2: Detect version ==========================
note "Step 2 — Detect release version"
@@ -263,55 +248,31 @@ else
fi
fi
-# ========================== Step 5: Docker Hub multi-arch image
==========================
-note "Step 5 — Docker Hub image: ${DOCKERHUB_REPO}"
+# ========================== Step 5: Verify Docker Hub image
==========================
+note "Step 5 — Verify Docker Hub image: ${DOCKERHUB_REPO}"
# CI (.github/workflows/publish-image.yaml) mirrors the multi-arch image
# to Docker Hub automatically on every `v*` tag push, so by the time
-# you're finalizing a passed vote this should already be live. We just
-# verify the two expected tags are present.
-#
-# Fallback: if CI didn't publish (workflow failed / secrets missing /
-# tag pushed before this workflow shipped), we fall back to the manual
-# `docker buildx imagetools create` mirror from the GHCR canonical tag
-# — same operation CI does, run locally. That needs Docker Hub push
-# rights on `apache/skywalking-ui`.
+# you're finalizing a passed vote it is already live. This step only
+# VERIFIES the expected tags are present — publishing is CI's job, there
+# is no local-push fallback.
DH_VERSION_TAG="${DOCKERHUB_REPO}:horizon-${RELEASE_VERSION}"
DH_LATEST_TAG="${DOCKERHUB_REPO}:latest"
-GHCR_SRC="ghcr.io/apache/skywalking-horizon-ui:${RELEASE_VERSION}"
echo "Expected on Docker Hub:"
echo " ${DH_VERSION_TAG} (immutable, this release)"
echo " ${DH_LATEST_TAG} (moving — newest Horizon
release)"
if docker buildx imagetools inspect "${DH_VERSION_TAG}" >/dev/null 2>&1; then
- echo "✓ ${DH_VERSION_TAG} already on Docker Hub — CI's publish-image
mirror succeeded."
- echo " Verify: docker buildx imagetools inspect ${DH_VERSION_TAG}"
+ echo "✓ ${DH_VERSION_TAG} is on Docker Hub — CI's publish-image mirror
succeeded."
+ echo " Inspect: docker buildx imagetools inspect ${DH_VERSION_TAG}"
else
- echo "✗ ${DH_VERSION_TAG} NOT on Docker Hub yet."
- echo " This is the expected outcome only if the publish-image workflow"
- echo " failed or didn't run on tag ${TAG}. Check:"
- echo "
https://github.com/apache/skywalking-horizon-ui/actions/workflows/publish-image.yaml"
- if ! docker buildx imagetools inspect "${GHCR_SRC}" >/dev/null 2>&1; then
- err "Source ${GHCR_SRC} not on GHCR either — CI didn't produce a
multi-arch"
- err "image to mirror. Re-run publish-image on ${TAG} from the Actions
UI"
- err "and then re-run this script."
- exit 1
- fi
- if confirm "Fall back to a manual local mirror from ${GHCR_SRC}?"; then
- docker buildx imagetools create \
- -t "${DH_VERSION_TAG}" \
- -t "${DH_LATEST_TAG}" \
- "${GHCR_SRC}"
- echo "Pushed multi-arch manifest to ${DOCKERHUB_REPO}."
- else
- echo "Skipped Docker Hub push — fix CI and re-run, OR run the
imagetools"
- echo "create manually:"
- echo " docker buildx imagetools create \\"
- echo " -t ${DH_VERSION_TAG} \\"
- echo " -t ${DH_LATEST_TAG} \\"
- echo " ${GHCR_SRC}"
- fi
+ err "✗ ${DH_VERSION_TAG} is NOT on Docker Hub."
+ err " CI's publish-image workflow did not mirror tag ${TAG}. The SVN
promote +"
+ err " GitHub release above already succeeded; only the image is missing.
Re-run"
+ err " the workflow (workflow_dispatch with tag ${TAG}), then re-run this
script:"
+ err "
https://github.com/apache/skywalking-horizon-ui/actions/workflows/publish-image.yaml"
+ exit 1
fi
# ========================== Done ==========================