Skip to content

Add nethserver-ns8-core skill - #7

Draft
stephdl wants to merge 11 commits into
mainfrom
ns8-core-skill
Draft

Add nethserver-ns8-core skill#7
stephdl wants to merge 11 commits into
mainfrom
ns8-core-skill

Conversation

@stephdl

@stephdl stephdl commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Description

The existing skills describe ns8-core from the outside. nethserver-ns8-module
explains how a module consumes the agent SDK and the Redis conventions.
nethserver-admin explains how to drive a live cluster over SSH. Neither covers
ns8-core as an object of development.

This adds nethserver-ns8-core, aimed at someone working inside a checkout of
NethServer/ns8-core.

The skill deliberately does not restate what the repository already documents. It
opens with a delegation index covering AGENTS.md, the three per-component
AGENTS.md files and all of docs/, then covers what none of them do:

  • repository map, including the artifacts that are easy to mistake, and the fact that
    the core is wider than this repository since update-core also updates ldapproxy,
    traefik, samba, openldap and loki
  • Redis namespace ownership across the cluster, node and module agents, and the rule
    that role keys go through cluster.grants
  • the four action and event roots, and the rule that only the cluster agent and
    api-server may LPUSH tasks
  • writing an action step: stdout belongs to the action so logs go to stderr,
    validation failures and broken invariants are signalled differently, tasks.run and
    run_helper are not interchangeable, and secrets are obscured only by key suffix
  • calling an action from the UI: the five ns8-ui-lib task services map to three
    queues, and the ForApp suffix selects the caller context, not the target
  • working on the core UI: the stack is a major generation behind the ecosystem
    defaults, core.css is built and served to every module UI, and the UI has a live
    localhost loop against a real node that the backend does not
  • api-server internals: action-based authorization with filepath.Match, a JWT that
    carries no permissions, GET bypassing authorization, the SQLite audit log, the
    progress/* WebSocket bridge
  • the three test loops and their cost
  • how a change reaches an installed cluster: the two stages of update-core, the
    three hook directories, and the rule that a hook can be replayed so it must converge

Two conventions the skill follows and states, so later edits keep them: it cites
files and identifiers but never line numbers, and it names version generations rather
than pinned numbers, since Renovate moves those on its own.

Verification

Done: every cited path exists at the current revision, no line numbers, no exact
version numbers, and the frontmatter of all eight skills in the plugin parses.

Not done yet: routing has not been exercised. The skill has to be picked up by a
marketplace refresh first. Before merging, someone should open a session on an
ns8-core checkout and confirm that core questions reach this skill while module
authoring questions still reach nethserver-ns8-module.

Draft for that reason, and because I would like a review on the scope split between
the two descriptions — they must not compete in the router.

stephdl added 11 commits August 25, 2026 19:35
The existing skills describe ns8-core from the outside: nethserver-ns8-module
explains how a module consumes the agent SDK and the Redis conventions,
nethserver-admin explains how to drive a live cluster. None of them covers
ns8-core as an object of development.

The new skill indexes what the ns8-core repository already documents in
AGENTS.md and docs/core, and fills the gaps nobody documents: Redis namespace
ownership, where the cluster and node actions and events live, api-server
authentication and authorization internals, the three test loops, and the
build-to-test-node iteration loop.
Match the reference block nethserver-admin already carries, including the
admin manual URL: core changes have to preserve the behaviour it documents.
The admin manual path copied from nethserver-admin returns 404, and the
handbook URL only redirects. Use the documentation hub, the administrator
manual, and handbook.nethserver.org directly. Every URL now returns 200.
Two things the ns8-core repository does not write down, both load-bearing in
the existing code.

Writing an action step: stdout is the action output so logs must go to stderr
with the SD_ prefixes, validation failures and broken invariants are signalled
differently, tasks.run and run_helper are not interchangeable, and the agent
only obscures secrets whose key ends with a known suffix. The section also
corrects the injected environment: cluster and node agents override AGENT_ID
and blank AGENT_BASEACTIONS_DIR, so they do not serve the base actions a
module agent inherits.

Calling an action from the UI: the five ns8-ui-lib task services map to three
queues, and the ForApp suffix selects the caller context, not the target.
AGENTS.md names Vue 2, Carbon and ns8-ui-lib and stops there. Add the four
things that cost time: the pinned versions are far enough behind the ecosystem
defaults that modern idioms fail to build, ns8-ui-lib is an external package so
a fix needs an upstream release and a version bump, core.css is concatenated at
build time and served to every module UI so a shared style change is not local,
and the build needs the openssl legacy provider with an immutable lockfile.
The docs/ui directory was missing from the delegation table, and two claims in
the UI section were wrong because of it.

ns8-ui-lib: npm serves 2.0.1 while core/ui pins ^1.12.4, and a caret never
crosses a major, so the core UI is a major behind on purpose. Module repos are
spread from ^1.3 to ^2.0. Testing a library change also does not need a
release: npm run build-pack produces a tarball that installs locally.

Iteration: the claim that everything goes through a container image is true of
the backend only. The UI runs on localhost with hot reload against a real
leader node, which needs config.development.js, GIN_MODE=debug to lift the CORS
check, and accepting the self-signed certificate once.
Renovate manages npm and gomod with an automerge preset, so any exact version
written here goes stale on its own. Replace the pinned numbers with the major
generations, which move rarely and are what actually changes the code being
written, and point at package.json and build-image.sh as the source of truth.

Same treatment for the ns8-ui-lib gap: the durable fact is that every consumer
pins with a caret and a caret never crosses a major, so the versions drift by
design. Give the three commands to check rather than a snapshot.

Also drop two counts that would drift without carrying information.
A stale line number points at the wrong code without ever saying so. A renamed
identifier returns nothing from grep and tells you it moved. Prefer the failure
mode that is loud.

Every citation now names a file and a symbol the prose already mentions, so the
reader can grep for it. The rule itself is stated in the delegation section, so
future edits keep the convention.

The agent environment override gains a single grep that shows the default, both
overrides and the consuming unit at once, which explains the mechanism better
than three separate line references did.
The description contains "Supports: ", and an unquoted YAML scalar cannot hold
a colon followed by a space: the parser reads it as a mapping and rejects the
document. GitHub refused to render the file, and the loader would have failed
the same way.

Every other skill in the plugin already single-quotes its description.
The skill presents itself as an index but cited five of the twenty-three pages
under docs/core and none of the six at the top level. Someone looking for the
firewall, the VPN, port allocation, certificates, user domains or the software
repositories found nothing and fell back to grepping, which is what the skill
exists to prevent.

Group the table by what the reader is looking for, and phrase each row as the
question rather than the file title. Call out the two pages that carry a
consequence: the API reference is generated from the validate-*.json schemas,
and CONTRIBUTING delegates the whole release process to
docs/development_process.md.
Building an image and installing it on a throwaway node proves the code runs;
it migrates nothing. A new Redis key, a changed grant or a renamed unit reaches
an existing installation only through an update-core hook, and neither AGENTS.md
nor the skill said so.

Describe the two stages of update-core, the three hook directories and when each
one runs, and the four rules that govern the scripts. The one that bites: a hook
can be replayed, so it must converge rather than apply a delta, and a non-zero
exit only warns instead of aborting, which is the opposite of an action step.

Also correct two things about the repository map. The core is wider than this
repository, since update-core also updates ldapproxy, traefik, samba, openldap
and loki from their own repositories. And the root-level dist/ and api-server/
are not empty leftovers but untracked local artifacts that git never had.

Add a pointer to nethserver-admin for the cluster CLI helpers rather than
redocumenting them, keeping only runagent, which replays an action step by hand
in the right agent environment.

Drop three common mistakes that restated the AGENTS.md conventions the skill
already delegates to, and replace them with the one this change introduces.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant