20 KiB
#
Nenjim
Documentation
Dokumentstatus: Journal-format version 1, den immutable Java-model, den interne tekstparser, det read-only
JournalService, den eksplicit refresh-baseredeJournalServiceManagerog første version af det centrale component Registry er implementeret. Contexts, resolution, discovery, runtime loading og removal er fortsat fremtidig funktionalitet.
Indholdsfortegnelse:
- 1. Introduktion til Nenjim
- 2. Versionering og Afhængigheder
- 3. Opdateringer og Sikkerhed
- 4. Betalingssystem og Integration med AssetAZ
- 5. Backing Store og Fleksibilitet
- 6. Standardiseret og Automatiseret Pakkehåndtering
- 7. Betydningen af Semantisk Versionering
- 8. Componenter og det centrale Registry
- 9. Integration med AssetAZ og økonomisk aktivitet
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 nuværende hardcodede componenter. 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:
<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:
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:
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.3og[1.0.3]er samme eksakte selector.[1.0]betyder hele den stabile1.0.x-serie, ikke eksakt1.0.0.[1.0.3-->1.0.7]inkluderer begge grænser;)ekskluderer øvre grænse.[1.0-->1.2]inkluderer hele1.2.x;[1.0-->1.2)gør ikke.[1.0-->stopper før2.0.0;(1.0-->starter ved1.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:
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:
BLACKLISTer en hård global regel: matchende releases må ikke vælges.DISCOURAGEDer et negativt hint: releasen kan stadig vælges.RECOMMENDEDer 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 derfor
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 start/stop,
filesystem paths, refresh, parser eller mutation.
En ServiceManager ejes af en composition/lifecycle owner og håndterer start, stop, configuration/data location,
refresh og adgang til den tilhørende Service. JournalServiceManager ejer den normaliserede Journal-root. Ved start
læser referenceimplementationen komplette UTF-8-filer kronologisk, validerer placement/navne og gør først sit
JournalService tilgængeligt, når hele initial loading er lykkedes. Refresh er explicit og idempotent; der er ingen
watcher eller background polling, og stop ændrer ikke Journal-filer.
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:
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
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; service-manageren 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 JournalServiceManagerImpl læser kun det dokumenterede lokale disk-layout. 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 bestemmes af den applikation, som bruger componenten; Registry-API'et bruger derfor det
fælles ord component og ikke plugin. NenjimComponent er en ren marker interface. En startbar component kan
desuden implementere NenjimApplication, som kun lover start() og ikke en fælles stop-operation.
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- og
application-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.
NenjimRegistryServiceManagerImpl konstruerer og starter Registry'et, registrerer Registry og manager først og
konstruerer derefter den nuværende hardcodede component graph i dependency order. Den package-private admin-view er
kun managerens registrationshandle og er hverken en component eller public API. Registration starter ikke et
objekt, og Registry'et forbliver internt åbent for senere registration efter startup.
Applikationen ejer sine konkrete valg og sin activation. Tickerens initiale configuration vælger eksplicit
assetaz.price-source.raydium-pool.eve-usdt gennem Registry'et; den hardcodede price source er registreret, men
inaktiv. Manageren starter kun den nuværende eksplicitte, dependency-safe liste: Ticker, Production Evelyn, Test
Evelyn, Production IOU Burner og Mission Control. Alarmen og øvrige tidligere udkommenterede applikationer bliver
ikke automatisk aktiveret. com.r35157.nenjim.hubd.Main er kun det yderste Java-bootstrap; Main.main(...) starter
manageren gennem NenjimApplication og er ikke selv en component eller applikation.
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 selection/start-all, usage tracking og permissions er fremtidigt arbejde. 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
- Partition 1
- 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
- Partition 1
- Disk 1:
- Lav nye tomme partitions tabeller
- Manual
- 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