530 lines
29 KiB
Markdown
530 lines
29 KiB
Markdown
#<center><H1>Nenjim<br>Documentation</H1></center>
|
||
|
||
> **Dokumentstatus:** Journal-format version 1, den immutable Java-model, den interne tekstparser, det read-only
|
||
> `JournalService` med en Hub-styret procesimplementation, den passive eksplicit refresh-baserede
|
||
> `JournalServiceManager`, den Hub-styrede `JavaFxRuntimeService`, første version af det centrale component Registry
|
||
> og den obligatoriske format 1 Hub-konfiguration er implementeret. Contexts, resolution, discovery, runtime loading
|
||
> og removal er fortsat fremtidig funktionalitet.
|
||
|
||
**Indholdsfortegnelse:**
|
||
<!-- TOC -->
|
||
* [1. Introduktion til Nenjim](#1-introduktion-til-nenjim)
|
||
* [2. Versionering og Afhængigheder](#2-versionering-og-afhængigheder)
|
||
* [3. Opdateringer og Sikkerhed](#3-opdateringer-og-sikkerhed)
|
||
* [4. Betalingssystem og Integration med AssetAZ](#4-betalingssystem-og-integration-med-assetaz)
|
||
* [5. Backing Store og Fleksibilitet](#5-backing-store-og-fleksibilitet)
|
||
* [6. Standardiseret og Automatiseret Pakkehåndtering](#6-standardiseret-og-automatiseret-pakkehåndtering)
|
||
* [7. Betydningen af Semantisk Versionering](#7-betydningen-af-semantisk-versionering)
|
||
* [8. Componenter og det centrale Registry](#8-componenter-og-det-centrale-registry)
|
||
* [9. Integration med AssetAZ og økonomisk aktivitet](#9-integration-med-assetaz-og-økonomisk-aktivitet)
|
||
<!-- TOC -->
|
||
|
||
## 1. Introduktion til Nenjim
|
||
Nenjim skal på sigt kunne håndtere forskellige versioner af softwareartifakter samtidigt. Det nu implementerede
|
||
fundament er Journal-laget: et strengt tekstformat og en immutable model, som kan fastholde, hvad der var kendt om
|
||
en artifakt på et bestemt tidspunkt. Det første Registry kan desuden katalogisere de konstruerede componenter, og
|
||
Hub-konfigurationen vælger den manuelt ordnede procesmængde. Dependency-resolution, Contexts, downloading og
|
||
classloading kommer senere.
|
||
|
||
## 2. Versionering og Afhængigheder
|
||
Nenjim beskriver moduler, artifakter, releases, relationer og versionspolitik i Journaler. Almindelig Java-kode skal
|
||
ikke indbygge Nenjim- eller versionsspecifikke navne for at bruge et API. Et Context beskriver de ønskede valg, og
|
||
Nenjim resolver senere disse valg og Journalernes metadata til en eksakt artifakt- og dependency-graf.
|
||
|
||
### 2.1 Én Journal per artifakt
|
||
|
||
En Journal beskriver præcis én artifakt. API, tests og referenceimplementation har derfor hver sin Journal; roller
|
||
som `API`, `IMPLEMENTATION` og `TEST` gemmes ikke som et `TYPE`-felt. Journalens identitet udledes af metadata:
|
||
|
||
```text
|
||
<GROUP>-<MODULE>-<ARTIFACT>
|
||
```
|
||
|
||
Eksempelkoordinater er `com_r35157_nenjim-hubd-api`, `com_r35157_nenjim-hubd-tests` og
|
||
`com_r35157_nenjim-hubd-impl_ref`. En komplet release-reference tilføjer en eksakt Semantic Version:
|
||
|
||
```text
|
||
com_r35157_nenjim-hubd-api:1.0.3
|
||
```
|
||
|
||
Der findes intet separat `JOURNAL_ID`.
|
||
|
||
### 2.2 Metadata og release-indhold
|
||
|
||
`[METADATA]` indeholder coordinate-delene og en obligatorisk single-quoted `DESCRIPTION`. Den valgfrie
|
||
`INFORMATION_URI` er også single-quoted, skal være en syntaktisk gyldig absolut `URI`, og kan bruge enhver scheme,
|
||
for eksempel `https:`, `ftp:` eller `ipfs:`. Nenjim åbner eller fortolker ikke URI'en automatisk.
|
||
|
||
Hver `[RELEASE major.minor.patch]` indeholder sin egen single-quoted `LICENSE`, `PUBLISHED_AT`, `CONTENT_SIZE` og
|
||
mindst én `CONTENT_DIGEST`. Format 1 accepterer valideret `sha256` og CIDv1 (`cid1`). Licensen er fri tekst, gemmes
|
||
uden normalisering og kan være forskellig mellem releases; fremtidig licensfiltrering er ikke implementeret.
|
||
|
||
### 2.3 Komplette snapshots og Journal-kæden
|
||
|
||
Hver Journal-fil er et komplet immutable snapshot af al aktuel viden om artifakten og dens kendte releases. En
|
||
revision er aldrig en delta og arver intet implicit. En nyere revision kan ændre metadata, policy, dependencies og
|
||
selv korrigere eller fjerne tidligere kendt release-information. Et no-op snapshot er også gyldigt.
|
||
|
||
`JOURNAL_VERSION` er et strengt stigende UTC-timestamp med millisekundpræcision:
|
||
|
||
```text
|
||
uuuuMMddHHmmssSSS'Z'
|
||
```
|
||
|
||
Genesis-revisionen udelader `PREVIOUS_JOURNAL_DIGEST`. Hver efterfølger refererer til SHA-256 over forgængerens
|
||
komplette UTF-8-tekst præcis som leveret, inklusive whitespace og linjeskift. Manglende forgængere, forks, flere
|
||
genesis-revisioner, fremmede artifaktkæder og ikke-stigende versioner afvises.
|
||
|
||
`PUBLISHED_AT` er release-tid og er uafhængig af Journalens publiceringstid. Historiske queries vælger et helt
|
||
snapshot ud fra Journal-kæden; de filtrerer ikke det nyeste snapshot efter `PUBLISHED_AT`.
|
||
|
||
### 2.4 Version expressions
|
||
|
||
En `SemanticVersion` (`1.0.3`) er én eksakt release. En `VersionExpression` beskriver et sæt acceptable releases:
|
||
|
||
* `1.0.3` og `[1.0.3]` er samme eksakte selector.
|
||
* `[1.0]` betyder hele den stabile `1.0.x`-serie, ikke eksakt `1.0.0`.
|
||
* `[1.0.3-->1.0.7]` inkluderer begge grænser; `)` ekskluderer øvre grænse.
|
||
* `[1.0-->1.2]` inkluderer hele `1.2.x`; `[1.0-->1.2)` gør ikke.
|
||
* `[1.0-->` stopper før `2.0.0`; `(1.0-->` starter ved `1.1.0`.
|
||
* Komma adskiller en union af expressions.
|
||
|
||
Endpoints skal mindst indeholde major og minor. Matematiske operatorer som `>=`, prereleases, build-metadata,
|
||
tomme elementer, omvendte ranges og implicitte cross-major open ranges afvises.
|
||
|
||
### 2.5 Dependencies
|
||
|
||
Dependencies hører til en bestemt artifaktrelease og bruger altid en explicit scheme. Format 1 implementerer kun:
|
||
|
||
```text
|
||
DEPENDS_ON=nenjim:com_r35157_nenjim-hubd-api=[1.0-->
|
||
EXCLUDES=nenjim:com_r35157_nenjim-hubd-api=1.0.5:'Known incompatibility'
|
||
PREFERRED=nenjim:com_r35157_nenjim-hubd-api=1.0.3:'Built together'
|
||
```
|
||
|
||
`DEPENDS_ON` er basissættet. `EXCLUDES` er en hård relationel begrænsning. `PREFERRED` er kun et hint og skal være
|
||
en delmængde af `DEPENDS_ON - EXCLUDES`. Flere exclusion/preference-linjer for samme target kombineres som union,
|
||
men deres individuelle beskrivelser bevares. Ukendte schemes, herunder `maven:`, afvises i format 1.
|
||
|
||
### 2.6 Artifact policy
|
||
|
||
Den valgfrie `[POLICY]` bevarer individuelle regler og beskrivelser:
|
||
|
||
* `BLACKLIST` er en hård global regel: matchende releases må ikke vælges.
|
||
* `DISCOURAGED` er et negativt hint: releasen kan stadig vælges.
|
||
* `RECOMMENDED` er et positivt hint til én eksakt release, som findes i samme snapshot.
|
||
|
||
Overlap er tilladt, og hårde regler vinder over hints. En fremtidig resolver bør søge en gyldig graf med flest muligt
|
||
kompatible anbefalinger; højeste versionsnummer er fallback, ikke en ubetinget regel. Det kan senere føre til
|
||
konvergens fra en højere lokal release til en lavere anbefalet release, men den adfærd er ikke implementeret nu.
|
||
|
||
### 2.7 Parser og immutable model
|
||
|
||
Parseren kræver `FORMAT_VERSION=1` som første faktiske entry, men tillader blanke linjer og `#`-kommentarer.
|
||
`#` inde i single quotes er tekst. Quoted værdier understøtter `\'` og `\\`. Ukendte, malformed, duplikerede eller
|
||
forkert placerede felter/sektioner afvises med source, linjenummer og årsag. Hele dokumentet valideres før servicens
|
||
state ændres. Alle publicerede modeller og collections er immutable og defensivt kopieret.
|
||
|
||
### 2.8 JournalService, JournalServiceManager og disk-layout
|
||
|
||
En `Service` er det domæne-API, som applikationer og andre services bruger i daglig drift. `JournalService` er en
|
||
registrerbar Nenjim component, men API'et er fortsat filesystem-uafhængigt og read-only: det kan vise coordinates,
|
||
kronologiske revisionslister, latest, exact og newest-at-or-before snapshots samt en eksakt release fra et valgt
|
||
snapshot. Det eksponerer ikke lifecycle, filesystem paths, refresh, parser eller mutation. Queries er først
|
||
tilgængelige, når Journal-processens initiale loading er lykkedes.
|
||
|
||
En `ServiceManager` er et separat administrationshandle, som en composition/lifecycle owner kan beholde uden at
|
||
give almindelige service-consumers administrative rettigheder. `JournalServiceManager` er passiv og eksponerer kun
|
||
den normaliserede Journal-root og explicit refresh; den har ingen `start()`, `stop()` eller service-accessor og er
|
||
hverken component eller process. Hub'en konstruerer ét Journal-objekt, som både er `JournalService` og
|
||
`NenjimProcess`, samt en separat manager bundet til objektets package-private admin-view.
|
||
|
||
Når Hub'en starter Journal-processen, læser referenceimplementationen komplette UTF-8-filer kronologisk og
|
||
validerer placement/navne. Hele den initiale worldview publiceres først, når alle runtime-filer er accepteret; en
|
||
fejl efterlader servicen utilgængelig uden partial state og samme instans kan ikke startes igen. Refresh efter
|
||
vellykket startup er fortsat explicit, idempotent og per-ingestion atomisk; der er ingen watcher eller background
|
||
polling.
|
||
|
||
`JournalServiceImpl` vedligeholder internt kæderne og udfører atomisk ingestion med exact-text SHA-256. Identisk tekst
|
||
er idempotent; anderledes tekst med samme coordinate og Journal-version er en conflict. Parser, ingestion og mutable
|
||
chain state er implementation details og findes ikke i public signatures. Public API-pakkerne er opdelt således:
|
||
|
||
```text
|
||
com.r35157.nenjim.service.journal JournalService, JournalServiceManager
|
||
com.r35157.nenjim.service.journal.model sammensatte immutable domænemodeller
|
||
com.r35157.nenjim.service.journal.valuetypes små værdidefinerede typer
|
||
com.r35157.nenjim.service.journal.exception Journal-specifikke exceptions
|
||
com.r35157.nenjim.service.journal.impl.ref referenceimplementation og interne helpers
|
||
```
|
||
|
||
```text
|
||
data/nenjim/journals/
|
||
└── <artifact-coordinate>/
|
||
├── <journal-version>.journal
|
||
└── <journal-version>.journal.example
|
||
```
|
||
|
||
Kun `.journal` er runtime-input. `.journal.example` dokumenterer formatet og indlæses ikke. Roden skal allerede
|
||
eksistere og være læsbar; Journal-processen og dens manager opretter, overskriver eller sletter ikke Journal-filer.
|
||
|
||
## 3. Opdateringer og Sikkerhed
|
||
Det implementerede Journal-lag kan repræsentere nye sikkerhedsoplysninger som en nyere immutable revision, for
|
||
eksempel via `BLACKLIST` eller en ændret `RECOMMENDED`. Automatisk synchronization, selection, reconciliation og
|
||
upgrade/downgrade er fremtidigt arbejde.
|
||
|
||
## 4. Betalingssystem og Integration med AssetAZ
|
||
Betaling og AssetAZ-integration er langsigtet vision og er ikke en del af Journal-formatet eller denne implementation.
|
||
|
||
## 5. Backing Store og Fleksibilitet
|
||
Den nuværende Journal-proces læser kun det dokumenterede lokale disk-layout gennem en intern filesystem-loader.
|
||
Artifact downloading, IPFS retrieval, remote Journals og andre backing stores er ikke implementeret. En
|
||
`ipfs:`-værdi i `INFORMATION_URI` er metadata, ikke en retrieval-instruks.
|
||
|
||
## 6. Standardiseret og Automatiseret Pakkehåndtering
|
||
Journalen modellerer dependency-krav og indholdsidentiteter, men downloader ikke bytes og verificerer ikke downloadet
|
||
indhold. Dependency-graph resolution, automatisk release-selection og Maven-resolution er fremtidigt arbejde.
|
||
|
||
## 7. Betydningen af Semantisk Versionering
|
||
Format 1 accepterer kun stabile eksakte releases med alle tre numeriske komponenter. Det forudsætter ikke, at en
|
||
resolver altid vælger den numerisk højeste version: hard constraints afgrænser de gyldige valg, og policy/dependency
|
||
hints kan på sigt foretrække en lavere kompatibel release.
|
||
|
||
## 8. Componenter og det centrale Registry
|
||
|
||
En Nenjim component er en færdigkonstrueret byggeklods, som er klar til brug. Rollen som service, applikation,
|
||
algoritme eller adapter og klassifikationen som aktiv proces er uafhængige dimensioner. En service eksponerer et
|
||
domain API, mens en applikation beskriver en user-facing eller orchestration-rolle. Registry-API'et bruger det
|
||
fælles ord `component` og ikke `plugin`, og `NenjimComponent` er en ren marker interface. En component, som Hub'en
|
||
kan starte og tracke, implementerer desuden den canonical `com.r35157.nenjim.process.NenjimProcess`, som kun lover
|
||
`start()` og ikke en fælles stop-, restart- eller health-operation. En service- eller applikationsimplementation kan
|
||
derfor også være en process; passive componenter er det ikke.
|
||
|
||
Ticker følger denne opdeling: almindelige consumers modtager `TickerService` med kun latest-price query, mens det
|
||
samme `TickerServiceImpl`-objekt separat er en `NenjimProcess`, som Hub'en starter. Tickerens source-lifecycle er
|
||
implementation-owned; `PriceSource`-instanser startes internt, og en fejlet Ticker-start stopper de sources, som nåede
|
||
at starte. Der findes ingen almindelig Ticker-serviceoperation til start eller stop.
|
||
|
||
Evelyn IOU Burner følger samme opdeling, selv om dens nuværende domain-service-view er tomt:
|
||
`EvelynIOUBurnerService` giver typed Registry- og dependency-identitet uden eksterne håndtag, mens det samme
|
||
`EvelynIOUBurnerServiceImpl`-objekt separat er en Hub-styret `NenjimProcess`. Kun process-view'et eksponerer startup;
|
||
hverken service-interfacet eller implementationen eksponerer almindelig stop eller restart.
|
||
|
||
En `NenjimComponentId` er registration metadata i ét Registry og er ikke en egenskab ved objektet. ID-formatet er
|
||
lower-case ASCII med dot-separated segments og valgfrie interne bindestreger, f.eks. `nenjim.registry.service` og
|
||
`assetaz.price-source.raydium-pool.eve-usdt`. Det samme objekt må registreres under flere forskellige ID'er, og én
|
||
registration bliver automatisk synlig gennem alle component interfaces, som objektet implementerer. Registry-
|
||
service- og process-view af Registry-objektet har derfor samme ID og samme object identity.
|
||
|
||
`NenjimRegistryService` er det read-only katalog, som almindelige consumers modtager gennem constructor injection.
|
||
Det kan returnere et immutable registration-order snapshot af ID'er for et component interface eller slå ét ID op
|
||
gennem et forventet interface. Et manglende ID giver `null`; et eksisterende ID med forkert interface er en caller
|
||
programming error. Public API'et kan ikke registrere eller fjerne componenter.
|
||
|
||
`NenjimHubImpl` repræsenterer én kørende Nenjim runtime. Hub'en læser deployment-konfigurationen, ejer dependency
|
||
wiring og lifecycle, konstruerer hele den nuværende passive component graph og konstruerer kun de processer, som er
|
||
valgt til autorun. Et implementation-only Registry assembly udleverer read-only service-view, process-view af det
|
||
samme Registry-objekt og en separat `NenjimRegistryServiceManager`. Manageren er kun Hub'ens passive
|
||
registrationshandle: den er hverken component eller process, har ingen `start()` eller service-accessor, registreres
|
||
ikke og starter aldrig en component.
|
||
|
||
Et tilsvarende implementation-only Journal assembly udleverer read-only service-view, process-view af det samme
|
||
Journal-objekt og en separat passiv `JournalServiceManager`. Journal-manageren registreres ikke og giver kun adgang
|
||
til root og refresh gennem et package-private admin-view; almindelige `JournalService`-consumers kan ikke udlede
|
||
administrationsadgangen.
|
||
|
||
Alle moderne JavaFX-applikationer deler ét JVM-wide JavaFX toolkit. Det repræsenteres af
|
||
`JavaFxRuntimeService`, mens samme `JavaFxRuntimeServiceImpl`-objekt også implementerer `NenjimProcess` for Hub'ens
|
||
lifecycle. Når den er valgt, konstruerer og registrerer Hub'en objektet som `nenjim.javafx-runtime.service`; den skal
|
||
stå før valgte JavaFX-applikationer i autorun-listen, så dens service-view kan injiceres efter vellykket startup. Kun
|
||
processens `start()` må kalde `Platform.startup(...)`; `runLater(...)` starter aldrig toolkit'et implicit og afviser
|
||
arbejde, indtil startup er lykkedes. Startup venter på JavaFX Application Thread og sætter
|
||
`Platform.setImplicitExit(false)`. Udelades alle JavaFX-processer, konstruerer Hub'en ikke runtime-objektet og
|
||
initialiserer ikke toolkittet.
|
||
|
||
Den package-private `NenjimRegistryServiceAdmin` er managerens interne mutationsadgang. Den må ikke gøres public,
|
||
fordi almindelige consumers ellers kunne caste deres Registry-service til mutationsinterfacet og bryde det
|
||
read-only service contract. Registration starter ikke et objekt, og Registry'et forbliver internt åbent for senere
|
||
registration efter startup.
|
||
|
||
### 8.1 Obligatorisk `NenjimHub.conf` format 1
|
||
|
||
Hub'en læser kun `conf/NenjimHub.conf`. Filen skal eksistere som en læsbar regular file; en manglende eller ugyldig
|
||
fil stopper startup, før Registry startes. `conf/NenjimHub.conf.example` er kun en versioneret copy-template: Hub'en
|
||
læser, kopierer og genererer den aldrig og falder hverken tilbage til den eller til en hardcoded procesliste.
|
||
|
||
Den første faktiske entry skal være `FORMAT_VERSION=1`; før den må der kun stå blanke linjer og full-line
|
||
`#`-kommentarer. Den næste faktiske entry skal være den ene eksakte `[AUTO_START]`-header. Hver aktiv linje i
|
||
sektionen er ét `NenjimComponentId`, og rækkefølgen bevares præcist. Leading/trailing whitespace ignoreres, en trimmet
|
||
linje som begynder med `#` er en kommentar, og `#` efter faktisk indhold starter en trailing kommentar. Inde i
|
||
sektionen fortsætter en comment-only line listen, mens den første whitespace-only line afslutter sektionen; EOF kan
|
||
også afslutte den. Efter afslutningen tillades kun blanke linjer og kommentarer. Formatet har ingen quoting eller
|
||
escaping for `#`.
|
||
|
||
Hele listen valideres før første proces-start. Ugyldige, duplikerede, ukendte og passive component-ID'er afvises.
|
||
Registry skal stå præcis én gang først og Journal præcis én gang som nummer to. De kendte valgbare processer er:
|
||
|
||
```text
|
||
nenjim.registry.service
|
||
nenjim.journal.service
|
||
assetaz.ticker.default
|
||
jupiter-perps-alarm.default
|
||
evelyn.status.prod
|
||
evelyn.status.test
|
||
evelyn.iou-burner.prod
|
||
evelyn.perps.default
|
||
nenjim.javafx-runtime.service
|
||
evelyn.mission-control.default
|
||
nenjim.process-manager.default
|
||
```
|
||
|
||
Ved opgradering erstattes `evelyn.service.prod` med `evelyn.status.prod` og
|
||
`evelyn.service.test` med `evelyn.status.test` i deploymentets private `conf/NenjimHub.conf`, hvor de forekommer.
|
||
Bevar rækkefølge og aktive/udkommenterede valg. De gamle ID'er accepteres ikke længere. Hub'en konstruerer samme
|
||
navngivne `Production`- og `Test`-instanser gennem `EvelynStatusServiceImpl` og injicerer deres
|
||
`EvelynStatusService`-views i Mission Control. Process Manager viser de nye ID'er fra Hub'ens startup-snapshot.
|
||
Historik ligger fortsat i `data/evelyn/<instance-name>/status.log` med formatversion 1 og kræver ingen migration.
|
||
|
||
Mission Control kræver også `evelyn.perps.default` før `evelyn.mission-control.default` i den private
|
||
`conf/NenjimHub.conf`. Hub'en konstruerer, registrerer og starter `EvelynPerpsServiceImpl` som en separat
|
||
proces og injicerer samme objekts read-only `EvelynPerpsService`-view i EMC. Process Manager viser ID'et efter
|
||
vellykket startup. Den lokale udviklingskonfiguration vælger nu servicen før EMC; andre deployments med EMC
|
||
skal tilføje samme linje. Udeladt eller forkert rækkefølge giver en tydelig konstruktionsfejl uden automatisk
|
||
indsættelse. Servicen bruger kun uændrede in-memory-eksempler og foretager ingen eksterne positionskald.
|
||
|
||
Hvis `evelyn.iou-burner.prod` vælges, skal både `assetaz.ticker.default` og
|
||
`evelyn.status.prod` stå før den. Hub'en injicerer Production status-servicen til
|
||
referenceprisopslag før nye buybacks; en manglende eller senere status-forgænger
|
||
giver en tydelig konstruktionsfejl uden implicit oprettelse eller omordning.
|
||
|
||
Efter validering konstruerer og starter Hub'en Registry, registrerer det som `nenjim.registry.service` og registrerer
|
||
startup-milepælen. Derefter konstrueres og registreres hele den nuværende passive graph uden at starte workers eller
|
||
processer. Først herefter behandles resten af `[AUTO_START]` i den angivne rækkefølge, begyndende med Journal. Hver
|
||
valgt proces konstrueres først, når dens linje nås, registreres før `start()` og tilføjes kun til Hub'ens immutable
|
||
ordered snapshot, når `start()` returnerer. Journal er derfor stadig den anden succesfulde proces, selv om den passive
|
||
graph konstrueres mellem Registry- og Journal-start.
|
||
|
||
`[AUTO_START]` er foreløbig deploymentets komplette, manuelt ordnede proces-dependency closure. Hub'en finder,
|
||
indsætter eller omordner ikke dependencies. En krævet proces skal stå før sin consumer; eksempelvis skal
|
||
`nenjim.javafx-runtime.service` stå før Mission Control og Process Manager. Mangler forgængeren, stopper konstruktion
|
||
eller startup fail-fast uden implicit reparation. En udeladt proces bliver hverken konstrueret, registreret, startet
|
||
eller vist af Process Manager. Den versionerede template vælger kun de obligatoriske Registry- og Journal-processer;
|
||
alle øvrige processer skal tilføjes eksplicit til deploymentets private konfiguration.
|
||
|
||
Et minimalt headless eksempel, svarende til den versionerede template, er:
|
||
|
||
```text
|
||
FORMAT_VERSION=1
|
||
|
||
[AUTO_START]
|
||
nenjim.registry.service
|
||
nenjim.journal.service
|
||
```
|
||
|
||
Tickerens egen component-konfiguration vælger fortsat eksplicit
|
||
`assetaz.price-source.raydium-pool.eve-usdt` gennem Registry'et; den hardcodede price source er registreret, men
|
||
inaktiv. Fejl under passiv konstruktion, valgt proceskonstruktion, registration eller startup stopper straks og
|
||
forhindrer alle senere processer. Tidligere succeser forbliver synlige, den fejlende proces registreres ikke som
|
||
startet, og der udføres ingen generic rollback. Online point og det afsluttende blocking wait nås kun efter alle
|
||
konfigurerede processer er startet. Process Manager viser fortsat Hub'ens faktiske succesfulde snapshots og ikke den
|
||
ønskede konfigurationsliste.
|
||
|
||
`com.r35157.nenjim.hubd.Main` er kun det yderste Java-bootstrap. `Main.main(...)` konstruerer `NenjimHubImpl` gennem
|
||
det globale `NenjimHub`-interface og kalder `start()` præcis én gang. Hub'en ejer også det eksisterende online point
|
||
og den afsluttende blocking wait. Hub'en er hverken component eller process og registreres ikke i sit eget Registry.
|
||
|
||
Det implementerede Registry er ét katalog og er ikke et authorization-system. Contexts, artifact-version semantics,
|
||
resolution, classloading, automatic discovery, public runtime loading/registration, removal, persistence, events,
|
||
automatic dependency construction/start-all, usage tracking og permissions er fremtidigt arbejde. Den nuværende
|
||
autorun-fil er ikke Context resolution eller process discovery. Journal publishing, remote synchronization og
|
||
signature validation er ligeledes ikke implementeret.
|
||
|
||
## 9. Integration med AssetAZ og økonomisk aktivitet
|
||
Økonomi, publicering og distribution er fremtidig vision. Format 1 beskriver alene artifaktviden; det indeholder
|
||
ingen betalings-, salgs- eller transaktionsadfærd.
|
||
|
||
## 10. Installation af en NenjimHub
|
||
For at NenjimHub'en kan køre godt, skal den leve i et samspil med nogle andre komponenter. Dette kan sættes op på
|
||
forskellige måder. Efterfølgende er et eksempel på en opsætning i en Virtuel Maskine, eller en lille fysisk host.
|
||
Bemærk at ECC ram er kritisk for stabiliteten, specielt hvis NenjimHub'en skal arbejde med finansielle aktiviteter.
|
||
Efterfølgende er en beskrivelse af hvordan man laver en opsætning som virker. Du kan lave specielle rettelser, hvis
|
||
du forstår hvad du laver. Det vil dog være en god idé at følge en standard opsætning, så alt bliver lidt nemmere
|
||
at styre.
|
||
|
||
## 10.1 Reference opsætning af Fysisk eller Virtuel Maskine (VM) til NenjimHub
|
||
Her beskrives hvordan man laver en standard opsætning af en NenjimHub. Denne opsætning vil også blive refereret til
|
||
som reference opsætningen, sådan at man har et fælles udgangspunkt at tale ud fra.
|
||
|
||
## 10.1.2 Minimale system krav
|
||
Det er klart at jo mere NenjimHub'en skal lave, jo større er hardware kravene, men med en 'NenjimHub Reference
|
||
Configuration', får du en opsætning der kan starte op og som du kan bygge videre fra.
|
||
Derfor er kravene til opsætningen meget moderate.
|
||
* CPU: 64bit x86
|
||
* RAM: 2GB (Helst ECC)
|
||
* Storage: 2x16GB (for RAID)
|
||
* Networking: Public IPv4 access
|
||
|
||
## 10.1.3 Basis Operativ System installation
|
||
Hvis du installerer som en VM (Proxmox), så brug følgende:
|
||
* Aktiver Qemu Agent
|
||
* Virtual Machine type: q35
|
||
* BIOS: OVMF (UEFI - med EFI disk + Pre-Enrolled keys)
|
||
* Storage: 2 x 16GB (SSD emulation + Discard)
|
||
* CPU: 2 CPU cores (type: x86-64-v2-AES)
|
||
* Memory: 2GB (Minimum 1GB + Ballooning)
|
||
* Network: Adgang til et netværk med DHCP service (Fravælg Proxmox firewall)
|
||
|
||
Installer basis Operativ System:
|
||
- Boot installations medie for Debian-13
|
||
- Vælg defaults med mindre andet angivet nedenfor
|
||
- User setup:
|
||
- Full name: System Operator
|
||
- Username: sysop
|
||
- Partition disks:
|
||
- Manual
|
||
- Lav nye tomme partitions tabeller
|
||
- Disk 1:
|
||
- Partition 1
|
||
- Size: 512MB
|
||
- Name: EFI1
|
||
- Use as: EFI System Partition
|
||
- Bootable: on
|
||
- Partition 2
|
||
- Size: 8GB
|
||
- Name: ROOT1
|
||
- Use as: Ext4
|
||
- Label: ROOT
|
||
- Partition 3
|
||
- Size: 8.7GB (Resten af disken)
|
||
- Name: ZFS1
|
||
- Use as: do not use
|
||
- Disk 2:
|
||
- Partition 1
|
||
- Size: 512MB
|
||
- Name: EFI2
|
||
- Use as: do not use
|
||
- Partition 2
|
||
- Size: 8GB
|
||
- Name: ROOT2
|
||
- Use as: do not use
|
||
- Partition 3
|
||
- Size: 8.7GB (Resten af disken)
|
||
- Name: ZFS2
|
||
- Use as: do not use
|
||
- Acceptér ikke at opsætte swap endnu.
|
||
- Software selection:
|
||
- SSH server
|
||
- standard system utilities
|
||
- Reboot after installation
|
||
|
||
Install additional tools:
|
||
```
|
||
$ su -
|
||
# apt-get update; apt-get install -y htop zram-tools sudo tmux
|
||
# usermod -aG sudo sysop
|
||
(Log ud og ind igen)
|
||
# sudo bash
|
||
# vi /etc/default/zramswap
|
||
(Ret PRIORITY=1)
|
||
# sed -ri'.bak' '/^deb/ { /contrib/! s/$/ contrib/ }' /etc/apt/sources.list
|
||
# apt-get update
|
||
# mokutil --sb-state || sudo apt -y install mokutil && mokutil --sb-state
|
||
# apt install -y dkms sbsigntool shim-signed mokutil
|
||
# mokutil --import /var/lib/dkms/mok.pub
|
||
(Indtast en midlertidig adgangskode)
|
||
# apt-get install -y linux-headers-amd64 zfsutils-linux zfs-dkms zfs-zed
|
||
# reboot
|
||
(Når den blå skærm kommer, vælg 'Enroll MOK' og brug nu det password du valgte ovenover)
|
||
```
|
||
|
||
Opret ZFS pool:
|
||
```
|
||
$ sudo bash
|
||
# zpool create zfspool -O xattr=sa -o ashift=12 -O compression=lz4 -O checksum=sha512 -O dedup=on -O atime=off mirror /dev/sda3 /dev/sdb3
|
||
```
|
||
|
||
Opret swap:
|
||
```
|
||
$ sudo bash
|
||
# zfs create -V 4G -o compression=zle \
|
||
-o logbias=throughput -o sync=always \
|
||
-o primarycache=metadata -o secondarycache=none \
|
||
-o com.sun:auto-snapshot=false zfspool/swap
|
||
# mkswap -f /dev/zvol/zfspool/swap
|
||
# echo /dev/zvol/zfspool/swap none swap sw,pri=0 0 0 >> /etc/fstab
|
||
# swapon -av
|
||
```
|
||
|
||
Installér docker (using official repository instead of Debian repository):
|
||
```
|
||
$ sudo bash
|
||
# apt install -y apt-transport-https ca-certificates curl gpg
|
||
# curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg
|
||
# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/debian trixie stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||
# apt update
|
||
# apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||
# usermod -aG docker sysop
|
||
(Log out and in again)
|
||
```
|
||
|
||
Flyt docker storage til ZFS:
|
||
```
|
||
$ sudo bash
|
||
# systemctl stop docker
|
||
# zfs create -V 3G zfspool/var_lib_docker
|
||
# mkfs.ext4 /dev/zvol/zfspool/var_lib_docker
|
||
# rm -rf /var/lib/docker
|
||
# mkdir /var/lib/docker
|
||
# echo "/dev/zvol/zfspool/var_lib_docker /var/lib/docker ext4 defaults 0 2" >> /etc/fstab
|
||
# systemctl daemon-reload
|
||
# mount /var/lib/docker
|
||
# chmod 710 /var/lib/docker
|
||
# systemctl enable docker ; systemctl start docker
|
||
```
|
||
|
||
Installer ZeroTier:
|
||
```
|
||
$ sudo bash
|
||
|
||
# curl -fsSL 'https://raw.githubusercontent.com/zerotier/ZeroTierOne/main/doc/contact%40zerotier.com.gpg' | gpg --import
|
||
(Importer ZeroTier's signeringsnøgle)
|
||
|
||
# gpg --fingerprint contact@zerotier.com
|
||
(Check nøglen)
|
||
|
||
#if z=$(curl -fsSL 'https://install.zerotier.com/' | gpg --decrypt); then
|
||
echo "$z" | sudo bash
|
||
else
|
||
echo "Signaturtjek mislykkedes – kører ikke scriptet." >&2
|
||
exit 1
|
||
fi
|
||
(Henter og dekryperer (verificerer) install-scriptet og kører det kun hvis signaturen er OK)
|
||
```
|
||
|
||
Konfigurer ZeroTier net:
|
||
- Login på 'https://my.zerotier.com'
|
||
- Opret et nye netværk 'Create A Network'
|
||
(Som skal forbinde terminaler og AssetAZHub)
|
||
- Klik på det nye netværk
|
||
- Basic/Name: 'assetaz-<ditid>'
|
||
(f.eks 'assetaz-mortengh')
|
||
- Vælg et IP range, f.eks 192.168.192.*
|
||
- Forbind AssetAZHub til netværket (netværks id'et kan ses på websiden):
|
||
- # zerotier-cli join a8bea75acfa45477
|
||
- Autoriser den nye maskine på nettet. Dette gøres ved at trykke på 'Edit' ved maskinen på websiden, som nu
|
||
burde kunne se den. Autoriser den, giv den et navn og evt. en beskrivelse.
|
||
- Tryk 'Add IP' og giv den en IP adresse inden for det range du har valgt oven over (f.eks 192.168.192.1). Tryk 'Save'
|
||
- Se at AssetAZHub' nu kan pinge sig selv:
|
||
# ping 192.168.192.1
|
||
|
||
Forbind terminal (f.eks en Android telefon)
|
||
- Installer ZeroTier-One
|
||
- Forbind til det samme net som hub'en.
|
||
- Autoriser terminalen inde på ZeroTiers web side og set terminalen ip adresse til noget kendt f.eks 192.168.192.2.
|
||
(Så kører hub'en på *.1 og terminalen på *.2)
|
||
|
||
Opsæt locale
|
||
|
||
Opret Docker baby swarm cluster
|
||
```
|
||
```
|