Skip to content

Commit 6679318

Browse files
Hardening phases 4–8: behavioral tests, config cleanup + YAML, CLI, coherence, docs (#61)
* test(behavioral): mock-server harness + end-to-end C-ABI coverage The unit suites only ever used synthetic ProbeResults, so the real socket paths — exactly where the Phase 1-3 bugs lived — had zero coverage. Adds in-process mock servers on ephemeral 127.0.0.1 ports: - MockA2S (UDP): direct / challenge / silent modes. - MockSLP (TCP): normal / fragmented (two-segment) response. New test/behavioral_test.zig (zig build test-behavioral): - C-ABI end-to-end: init -> gossamer_gsa_probe (returns a handle >= 1000, not a result code) -> close_handle (ok) -> close again (double_free) -> unknown id (not_found). This single test would have caught findings 1-3 together — the seam the old tests never touched. - A2S 0x41 challenge handshake completes and parses. - Minecraft SLP is reassembled across a fragmented response. - A 100ms probe budget returns well under 1s against a silent server (the old code ignored timeout_ms and waited ~3000ms). build.zig gains the test-behavioral step (mirrors the smoke pattern) with a shared mock_servers module. CI now runs all five suites, incl. the two (smoke, property) that were defined but never run. 157 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TaWWedv6VQqeZaPvc94keN * refactor(config): delete dead parsers, real YAML support, wire fuzz harness Three related cleanups from the audit's Phase 5: 1. Delete 5 orphaned config_parse_{ini,json,kv,lua,xml}.zig (727 LOC). They duplicated logic already live and tested inline in config_extract.zig, were never referenced by build.zig, and had silently drifted (the fuzz harness below wouldn't even compile against the current API). 2. Real YAML parser, replacing the .YAML -> parseKeyValue stub. New parseYAML handles a scoped subset (block mappings -> dotted keys, block sequences -> parent.N, scalars, quotes, comments, ---/... markers), same complexity class as parseTOML/parseLua. detectFormat now recognises YAML via a leading --- or colon-mappings with no '=' lines/sections, without stealing from INI/TOML/ENV/KeyValue. The repo-wide '8 formats' claim is now true. Detection + nested-parse tests added. 3. Wire the orphaned fuzz_config.zig into (updated to the Zig 0.15 std.testing.fuzz two-arg testOne API). Running it immediately caught a real invariant violation: some parsers emitted config fields with an empty key (a lone '=value' line, a '"":x' JSON key), which breaks getField and A2ML emission. Fixed at the single addField funnel so 'every field has a non-empty key' now holds by construction. 159 tests green (+2 YAML) plus 104 in the fuzz seed run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TaWWedv6VQqeZaPvc94keN * fix(cli): stop truncating config reads, cover + document the Nickel patchers - config set-default / add-favorite read the user config into a fixed [16384]u8 buffer with a single read(), silently truncating (and then corrupting on rewrite) any config larger than 16 KiB. Switched both to readToEndAlloc(1 MiB). - Documented writeWithDefaultServer / writeWithFavorite as deliberately narrow, structure-aware patches of GSA's own generated user-config.ncl — explicitly not a Nickel parser — that pass unknown-shape input through unchanged rather than risk corruption. - Fixed the usage text: GSA_VERISIMDB_URL default printed http://[::1]:8090 but the code defaults to http://localhost:8090. - cli.zig had zero tests and was only built as an exe. Added a test-cli build step + 3 round-trip tests (set-default replace, favorite insert, unknown-shape passthrough) and wired test-cli + the fuzz seed run into CI. 162 tests green across six suites. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TaWWedv6VQqeZaPvc94keN * chore(coherence): wire nexus-setup panel, fill metadata TODOs, fix version outlier - nexus-setup was a shipped 61KB panel with no descriptor, clade, or manifest entry (README/groove listed 7 panels; STATE said 8). Added panels/nexus-setup/panel.json (+ manifest entry) and the gsa-nexus-setup clade (GsaNexusSetup.a2ml + config.k9.ncl), matching sibling structure. The GUI panel family is now consistently 8. - Filled the blank ECOSYSTEM.a2ml (purpose, role=ffi-infrastructure, the real related-projects/integration-points: gossamer/ephapax/verisimdb/groove/ standards, verisimdb/steam/groove/podman) and META.a2ml (type note, languages=[zig,idris2,ephapax]). - run.js version 0.3.0 -> 0.1.0 (stale outlier; matches main.zig, build.zig, panels, and all machine-readable files). - ROADMAP 'beyond 17' -> 'beyond the current 18' (18 profiles/clades exist). Deliberately DEFERRED (needs a maintainer decision, flagged in META.a2ml and the human checklist): the license reconciliation. The LICENSE file and all 27 Zig/Idris source headers are MPL-2.0, but the panel descriptors and META.a2ml declare AGPL-3.0-or-later — a genuine conflict that must not be resolved by an automated mass-edit in either direction. Also deferred: a full version bump to a single SSOT number + drift-check, pending the canonical version choice. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TaWWedv6VQqeZaPvc94keN * docs: config-format guide + release checklist; honest INDEX statuses Two concrete, accurate docs written from the code hardened in this series: - docs/developer/CONFIG-FORMATS.adoc — the 8 formats, most-specific-first detection order (incl. the INI-vs-JSON and YAML-vs-KeyValue disambiguation), the addField invariants (non-empty keys, secret redaction), the YAML subset scope, and how to add a parser. Marked live in INDEX (was 'planned'). - docs/maintainer/RELEASE-CHECKLIST.adoc — the actual CI gates (six test suites + the ABI-contract regen/diff/comptime + Idris typecheck), the version/license/docs pre-tag gates, the manual gates, and the tag steps. Marked live in INDEX (was 'planned'). INDEX also records why the empty-scaffolding prune is deferred: verification/, docs/theory/, docs/reports/, docs/wikis/ are referenced by the governance layer (ANCHOR.a2ml, MAINTENANCE-CHECKLIST, panic-attacker), so deleting them needs a reviewed change that updates those references in lockstep — not an automated docs pass. The remaining planned docs (FFI module reference, panel-extension guide, architecture rationale, CI/CD guide, security runbook) stay 'planned'. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TaWWedv6VQqeZaPvc94keN --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent e1b6ec3 commit 6679318

25 files changed

Lines changed: 978 additions & 763 deletions

.github/workflows/cross-platform.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,15 @@ jobs:
6868
- name: Property Tests
6969
working-directory: src/interface/ffi
7070
run: zig build test-property
71+
72+
- name: Behavioral Tests (mock servers)
73+
working-directory: src/interface/ffi
74+
run: zig build test-behavioral
75+
76+
- name: CLI Tests
77+
working-directory: src/interface/ffi
78+
run: zig build test-cli
79+
80+
- name: Fuzz seed corpus
81+
working-directory: src/interface/ffi
82+
run: zig build fuzz

.machine_readable/6a2/ECOSYSTEM.a2ml

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,31 @@
66

77
[metadata]
88
version = "0.1.0"
9-
last-updated = "2026-03-22"
9+
last-updated = "2026-07-02"
1010

1111
[project]
1212
name = "game-server-admin"
13-
purpose = "" # TODO: describe project purpose
14-
role = "" # TODO: describe project role # e.g. ffi-infrastructure, cli-tool, library, service
13+
purpose = "Universal game server probe, configuration management, and administration via Gossamer webview + VeriSimDB backing store. Extracts config into A2ML format with full provenance tracking. The client half of a multi-repo ecosystem."
14+
role = "ffi-infrastructure"
1515

1616
[position-in-ecosystem]
1717
tier = "infrastructure" # 1 | 2 | infrastructure
1818

1919
[related-projects]
2020
# relationship types: sibling-standard, dependency, dependent, inspiration, potential-consumer
21-
# - { name = "language-bridges", relationship = "sibling-standard" }
22-
# - { name = "hypatia", relationship = "potential-consumer" }
21+
related = [
22+
{ name = "gossamer", relationship = "dependency" }, # webview shell; loads libgsa via dlopen
23+
{ name = "ephapax", relationship = "dependency" }, # .eph GUI/bridge source language
24+
{ name = "verisimdb", relationship = "dependency" }, # 8-modality backing store (REST :8090)
25+
{ name = "groove", relationship = "potential-consumer" }, # voice/text alerting over .well-known
26+
{ name = "standards", relationship = "sibling-standard" }, # org reusable CI workflows
27+
]
2328

2429
[integration-points]
2530
# External systems this project connects to
26-
# - { system = "gitbot-fleet", direction = "outbound", protocol = "repository_dispatch" }
31+
integrations = [
32+
{ system = "verisimdb", direction = "outbound", protocol = "REST" },
33+
{ system = "steam-web-api", direction = "outbound", protocol = "HTTPS" },
34+
{ system = "groove", direction = "outbound", protocol = "HTTP" },
35+
{ system = "podman", direction = "outbound", protocol = "cli-exec" },
36+
]

.machine_readable/6a2/META.a2ml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ version = "0.1.0"
99
last-updated = "2026-03-22"
1010

1111
[project-info]
12-
type = "library" # TODO: update type (library|binary|service|website|monorepo) # library | binary | monorepo | service | website
13-
languages = [] # e.g. ["rust", "zig", "idris2"]
12+
type = "library" # libgsa.so is the primary artifact (+ the gsa CLI binary)
13+
languages = ["zig", "idris2", "ephapax"]
14+
# NOTE: license is unsettled and pending a maintainer decision. The LICENSE
15+
# file body and all Zig/Idris source SPDX headers are currently MPL-2.0, while
16+
# the panel descriptors declare AGPL-3.0-or-later and this field says AGPL —
17+
# a genuine conflict. See the human checklist / docs/legal (to be added once
18+
# the direction is chosen). Left as-is deliberately; do not mass-edit headers
19+
# without that decision.
1420
license = "AGPL-3.0-or-later"
1521
author = "Jonathan D.A. Jewell (hyperpolymath)"
1622

ROADMAP.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,6 @@ Test suites:
6565

6666
== Future
6767

68-
* Additional game profiles beyond 17
68+
* Additional game profiles beyond the current 18
6969
* Live server monitoring dashboard
7070
* Multi-server fleet management

docs/INDEX.adoc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ _You build GSA, extend it, or contribute code across the Gossamer GUI → Zig FF
4040
| FFI module reference | *planned* | Per-module docs for the 11 FFI modules (signatures, the 18 result codes, examples)
4141
| Panel extension guide | *planned* | The PanLL clade system; registering a new panel; inheriting base clades
4242
| Game-profile authoring | *thin* | Expand the README snippet: field types, validation, port/protocol, debugging
43-
| Config-format guide | *planned* | How to add a parser to the 8-format `config_extract`
43+
| `docs/developer/CONFIG-FORMATS.adoc` | live | The 8 formats, detection order, `addField` invariants, YAML scope, and how to add a parser
4444
| Architecture rationale | *planned* | Why Ephapax / Idris2 / Zig / VeriSimDB; when to touch each layer
4545
|===
4646

@@ -55,7 +55,7 @@ _You release, run CI/CD, operate containers, and manage governance + security sc
5555
| `docs/architecture/THREAT-MODEL.adoc` | live | STRIDE, assets, trust boundaries, mitigations
5656
| `docs/DEPLOYMENT-RUNBOOK.adoc` | live | Build, container, VeriSimDB main+backup, health, backup/restore
5757
| `SECURITY.md` | live | Vulnerability reporting
58-
| Release checklist | *planned* | v1.0.0 must/should/could + sign-off criteria
58+
| `docs/maintainer/RELEASE-CHECKLIST.adoc` | live | CI gates (6 suites + ABI contract), version/license/docs gates, manual gates, tag steps
5959
| CI/CD guide | *planned* | `.github/workflows/` structure, standards-estate reusables (pins `4ddc926`), staleness check, adding a check
6060
| Security-scanning runbook | *planned* | Running/interpreting Hypatia + panic-attack + Scorecard; the `.hypatia-ignore` suppression mechanism (NOT `.hypatia-baseline.json` — see `NEUROSYM.a2ml`)
6161
| Container/quadlet ops | *thin* | Expand the runbook: `.container` format, systemd user units, day-to-day ops
@@ -78,3 +78,11 @@ subtrees (`theory/`, `reports/`, parts of `practice/`).
7878
*Decision pending:* either populate `docs/wikis/` and sync it, **or** (recommended)
7979
consolidate all narrative under `docs/` using the three audience paths above and
8080
prune the empty scaffolding. Until then, this index is the single navigation point.
81+
82+
NOTE: a mechanical prune is **not** clean — `verification/`, `docs/theory/`,
83+
`docs/reports/`, and `docs/wikis/` are referenced by the governance layer
84+
(`.machine_readable/anchors/ANCHOR.a2ml`, `docs/governance/MAINTENANCE-CHECKLIST`,
85+
`features/panic-attacker/`). Deleting the trees without updating those references
86+
risks breaking governance/CI expectations, so the prune is deferred to a
87+
dedicated, reviewed change that updates the references in lockstep rather than
88+
bundled into an automated docs pass.

docs/developer/CONFIG-FORMATS.adoc

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// SPDX-License-Identifier: CC-BY-SA-4.0
2+
// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3+
= GSA Config-Format Guide
4+
:toc:
5+
:source-highlighter: rouge
6+
7+
How `src/interface/ffi/src/config_extract.zig` detects and parses game-server
8+
configuration files, and how to add support for a new format.
9+
10+
== Overview
11+
12+
GSA extracts a game server's configuration into a flat list of typed fields
13+
(`ParsedConfig.fields`), which the A2ML emitter then serialises with provenance.
14+
Every server config — whatever its on-disk syntax — is normalised into the same
15+
`ConfigField { key, value, field_type, label, default_val, range_min,
16+
range_max, is_secret }` shape.
17+
18+
Two entry points:
19+
20+
* `detectFormat(data) ConfigFormat` — sniff the format from the bytes.
21+
* `parseAuto(allocator, data) !ParsedConfig` — detect, then dispatch to the
22+
matching parser.
23+
24+
== The eight formats
25+
26+
[cols="1,3,2",options="header"]
27+
|===
28+
| `ConfigFormat` | Detection signal | Parser
29+
| `XML` | `<?xml` prefix, or `<` followed by a letter | `parseXML`
30+
| `JSON` | leading `{`, or `[` followed by `{`/`"`/digit/`-`/`tr`/`fa`/`nu` | `parseJSON` (delegates to `std.json`)
31+
| `TOML` | `[[table]]` headers, or `[section]` + dotted `a.b = c` keys | `parseTOML`
32+
| `INI` | `[section]` headers (no dotted keys) | `parseINI`
33+
| `ENV` | `export KEY=...` lines | `parseENV`
34+
| `Lua` | `key = { ... }` table literals | `parseLua`
35+
| `YAML` | leading `---`, or `key: value` mappings / `- item` sequences with **no** `=` lines | `parseYAML`
36+
| `KeyValue` | fallback: `key=value` / `key: value` with no other signal | `parseKeyValue`
37+
|===
38+
39+
Detection is deliberately ordered most-specific-first. The ambiguous cases are
40+
handled explicitly:
41+
42+
* `[network]` is INI, not a JSON array — the JSON branch requires a 2-character
43+
lookahead (`[tr`, `[fa`, `[nu`) before treating `[` + letter as JSON.
44+
* A `key: value` file with no `=` and no `[section]` is YAML, not KeyValue — but
45+
a bare `a=1` file stays KeyValue. `eq_lines == 0` is the discriminator, so a
46+
colon in a value (a URL, a sentence) does not trip YAML detection.
47+
48+
== Parser conventions
49+
50+
All parsers funnel field creation through `ParsedConfig.addField`. Two
51+
invariants are enforced there, once, for every format:
52+
53+
* **Non-empty keys.** A field whose key is empty (a lone `=value` line, a JSON
54+
key of `""`) is silently dropped — it would break `getField` lookup and A2ML
55+
emission. This invariant is asserted by the config fuzz harness
56+
(`zig build fuzz`).
57+
* **Secret redaction.** Keys containing `password`, `secret`, `token`, or
58+
`rcon.password` are flagged `is_secret = true`; the A2ML emitter renders their
59+
values as `[REDACTED]`.
60+
61+
Nested structures flatten to dotted keys: `server.rcon.password`,
62+
`worlds.0`, `worlds.1`. This is uniform across TOML, Lua, JSON, and YAML so
63+
downstream code never has to care which syntax a value came from.
64+
65+
=== YAML scope
66+
67+
`parseYAML` is a *scoped subset*, not a full YAML 1.2 implementation — the same
68+
level as `parseTOML`/`parseLua`. It handles:
69+
70+
* block mappings (indentation → dotted keys),
71+
* block sequences of scalars (`- item` → `parent.N`),
72+
* scalar values with optional single/double quotes,
73+
* `#` comments and `---` / `...` document markers.
74+
75+
Out of scope (documented, not silently wrong): anchors/aliases, flow
76+
collections (`{a: 1}`, `[1, 2]`), and multi-line/folded scalars.
77+
78+
== Adding a new format
79+
80+
. Add a variant to `ConfigFormat` (keep the integer stable — it crosses the
81+
ABI as a `u8`; mirror it in `GameServerAdmin.ABI.Types.ConfigFormat`).
82+
. Write `parseXYZ(allocator, data) !ParsedConfig`, routing every field through
83+
`addField` so the invariants above hold for free.
84+
. Add a detection branch to `detectFormat`, ordered by specificity, and be
85+
explicit about any ambiguity with existing formats.
86+
. Add the dispatch arm to `parseAuto`.
87+
. Add tests: a detection test (including a negative case proving you don't
88+
steal from an adjacent format) and a parse test asserting the flattened keys.
89+
The fuzz harness (`src/fuzz_config.zig`) will exercise the new parser on
90+
arbitrary bytes automatically once it is reachable from `parseAuto`.
91+
92+
== See also
93+
94+
* `docs/developer/ABI-FFI-README.adoc` — the ABI these fields cross.
95+
* `src/interface/ffi/test/integration_test.zig` — per-format parse tests.
96+
* `src/interface/ffi/src/fuzz_config.zig` — the fuzz harnesses.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// SPDX-License-Identifier: CC-BY-SA-4.0
2+
// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3+
= GSA Release Checklist
4+
:toc:
5+
6+
The steps to cut a GSA release. The release itself is automated —
7+
`.github/workflows/release.yml` fires on a `v*` tag, builds `libgsa` + the
8+
`gsa` CLI with Zig, packages a tarball, generates a `git-cliff` changelog, and
9+
attaches SLSA build-provenance. This checklist is what to verify *before*
10+
pushing the tag.
11+
12+
== Gate 1 — CI is green on `main`
13+
14+
All must pass on the commit you intend to tag:
15+
16+
* `Cross-Platform Build & Test` — `zig build` + the six test suites: `test`,
17+
`test-integration`, `test-smoke`, `test-property`, `test-behavioral`,
18+
`test-cli` (plus the `fuzz` seed corpus).
19+
* `ABI Contract` — `zig-contract` (regenerates `abi_layout_expected.zig` +
20+
`result_codes_expected.zig` from the Idris2 model and fails on drift; runs the
21+
comptime cross-check) **and** `idris-typecheck` (type-checks
22+
`src/interface/abi/gsa-abi.ipkg` in the pinned `idris2-pack` container).
23+
* `CodeQL`, `Scorecard`, SonarCloud quality gate, Hypatia scan (critical=0,
24+
high=0).
25+
26+
`panic-attack assail .` is the local pre-commit gate; the static-analysis CI
27+
workflow covers it when the estate tool is installed.
28+
29+
== Gate 2 — Version is reconciled
30+
31+
There is not yet a single-source-of-truth version. Before tagging, confirm the
32+
following agree on the release number: `src/interface/ffi/src/main.zig`
33+
(`VERSION`, `BUILD_INFO`), `src/interface/ffi/build.zig` (`.version` ×2),
34+
`run.js`, `panels/manifest.json`, `panels/*/panel.json`, and
35+
`.machine_readable/6a2/*.a2ml`. (Follow-up: a `scripts/check_version_drift.sh`
36+
CI gate once the canonical location is chosen.)
37+
38+
== Gate 3 — License is settled
39+
40+
*Blocking, one-time.* The LICENSE file + all Zig/Idris source SPDX headers are
41+
MPL-2.0; the panel descriptors and `META.a2ml` declare AGPL-3.0-or-later. Pick a
42+
direction, reconcile every artifact, and record it in `docs/legal/` before the
43+
first tagged release. See `.machine_readable/6a2/META.a2ml` for the flagged
44+
conflict.
45+
46+
== Gate 4 — Docs reflect reality
47+
48+
* `.machine_readable/6a2/STATE.a2ml` completion % and session history updated.
49+
* `docs/INDEX.adoc` statuses (`live`/`thin`/`planned`) match the tree.
50+
* `CHANGELOG` / release notes — `git-cliff` generates these from Conventional
51+
Commit messages, so confirm the commit log is clean.
52+
53+
== Manual gates (outside CI — see also the project human checklist)
54+
55+
These cannot be done by an agent and gate a *feature-complete* v1.0.0, not the
56+
mechanics of tagging:
57+
58+
[cols="1,3",options="header"]
59+
|===
60+
| Gate | Action
61+
| CryoFall staging (B4) | `STEAM_USER=… just cryofall-stage-verpex` (Steam password + Guard 2FA, ~3 GB, on Verpex), then `just cryofall-watchdog-install`
62+
| Bitbucket mirror (B2) | provision the SSH key / token; `mirror.yml` is already wired
63+
| OpenSSF badge | register at bestpractices.dev, add the badge to `README.md`
64+
| Merged-branch cleanup | `git push origin --delete <branch>` for the merged feature branches (Hypatia GS007)
65+
| Ephapax parser gaps | tracked externally (`nextgen-languages/ephapax`) — 2/25 Gossamer chain tests
66+
|===
67+
68+
== Cut the release
69+
70+
[source,bash]
71+
----
72+
git checkout main && git pull
73+
git tag -a vX.Y.Z -m "GSA vX.Y.Z"
74+
git push origin vX.Y.Z # release.yml does the rest
75+
----
76+
77+
Then verify the GitHub Release has the tarball, changelog, and provenance
78+
attestation attached, and that the `mirror.yml` run propagated the tag.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath)
3+
4+
[clade-metadata]
5+
id = "gsa-nexus-setup"
6+
name = "GSA Nexus Setup"
7+
short-name = "Nexus"
8+
version = "1.0.0"
9+
kind = "wizard"
10+
icon = "wand-sparkles"
11+
description = "Guided 7-step wizard to deploy a new managed game server: profile selection, Steam operators, configuration, target host, file staging, provisioning, and health verification. Mirrors the scripts/wizard.sh flow in the Gossamer GUI."
12+
13+
[clade-traits]
14+
has-backend = true
15+
has-scanning = false
16+
has-persistence = false
17+
has-work-items = false
18+
has-real-time = true
19+
is-directive = true
20+
is-readonly = false
21+
is-ambient = false
22+
23+
[clade-capabilities]
24+
capabilities = ["Network", "Shell", "ProcessSpawn", "Containerised"]
25+
26+
[clade-protocols]
27+
protocols = ["REST", "TauriIPC"]
28+
29+
[clade-taxonomy]
30+
inherits-from = "gsa"
31+
sibling-clades = ["gsa-actions", "gsa-config", "gsa-browser"]
32+
supersedes = ""
33+
34+
[clade-fli]
35+
fli-inherits = ["fli-terminal"]
36+
37+
[clade-panel-integration]
38+
panel-id = "PanelGsaNexusSetup"
39+
model-module = "GsaNexusSetupModel"
40+
component-module = "GsaNexusSetup"
41+
command-module = "GsaNexusSetupCmd"
42+
module-module = "GsaNexusSetupModule"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
{
3+
pedigree = {
4+
name = "gsa-nexus-setup-config",
5+
version = "1.0.0",
6+
author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>",
7+
leash = 'Kennel,
8+
},
9+
panel = {
10+
id = "GsaNexusSetup",
11+
short_name = "Nexus",
12+
description = "Guided 7-step wizard to deploy a new managed game server",
13+
has_backend = true,
14+
clade_id = "gsa-nexus-setup",
15+
isolation_tier = "native",
16+
},
17+
wiring = {
18+
model_slice = "gsaNexusSetup",
19+
msg_namespace = "gsaNexusSetupMsg",
20+
view_route = "PanelGsaNexusSetup",
21+
module_name = "GsaNexusSetup",
22+
},
23+
obligations = {
24+
requires_tests = true,
25+
requires_backend_health = true,
26+
requires_clade_manifest = true,
27+
},
28+
}

panels/manifest.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@
9292
"panels/live-logs/panel.json",
9393
"panels/health-dashboard/panel.json",
9494
"panels/config-history/panel.json",
95-
"panels/cross-search/panel.json"
95+
"panels/cross-search/panel.json",
96+
"panels/nexus-setup/panel.json"
9697
],
9798
"capabilities": [
9899
"Network",

0 commit comments

Comments
 (0)