| JobService | ListJobs (endast jobs-byggen; filter state = waiting/running/failed/done, holger admit-queue) | ja | ja | admin | Admin-sidan (/admin, fliken Queue) — BFF:en frågar med konsolens credential på /api/admin/jobs?state=…; admin-golv i middleware (ADMIN_READS) OCH i handlern, holger frågas aldrig för en lägre session; okänt state-ord nekas med 400 utan att holger frågas. Ingen klient i src/grpc.rs (wasm) | ja (501 = bygge utan jobs sägs ut) | backend-test (api::admin_queue: viewer/operator/utan session/förfalskad cookie nekas, 0 anrop till holger; admin får raderna, state når holger) + enhet (admin_queue) | Täckt via BFF | Wasm-koden anropar inte RPC:n själv | | JobService | JobRow-fälten stage=12, attempts=13, max_attempts=14, next_attempt_micros=15, priority=16 (jobbtyperna holger_fetch, holger_mirror_asset; status retry_wait med reason och nästa försök) | ja | ja | admin | Queue-fliken: status · stage, attempts/max, reason, nästa försök (UTC-tid + "in N s"), prioritetsklass (0 full, 1 reduced, 2 floor, 3 queued), requested_by | ja | enhet (admin_queue: tider, avrundning uppåt, klassord) | Täckt via BFF | — | | JobService | GetJob | ja | ja | admin | — (Ingen klient i src/grpc.rs; ingen detaljvy för ett jobb — listraden bär alla fält) | — | — | Ej byggd yta | Medvetet gap: ListJobs-raden är samma JobRow | | AdmissionService | ListUsage (varje konsument i usage-boken: fönster 30 d + i dag, per Work-typ estimerad/faktisk kostnad, klass, planens mening, in flight; dörrens policy och andelar) | ja | ja | admin | Admin-sidan, fliken Admission — BFF:en på /api/admin/admission (admin-golv i middleware + handler). Konsument: principal / paired peer / anonym dagstoken visad som "anonymous (today)". Under pass-through visas used/limit som "N/A (pass-through)", aldrig 0. Ingen klient i src/grpc.rs (wasm) | ja | backend-test (api::admin_queue: nekas under admin med 0 anrop; pass-through = bara ListUsage) + enhet (admin_queue: N/A aldrig 0) | Täckt via BFF | Wasm-koden anropar inte RPC:n själv | | AdmissionService | AdmitPlan (planen för en konsument och ett arbete nu: klass, mening, budget_left, andel) | ja | ja | admin | Admission-fliken: BFF:en frågar AdmitPlan (work download) en gång per namngiven konsument (principal:/peer:) + en gång anonymous (dagsbudgeten för en färsk token) — limit = used + budget_left; en nekad plan visas med holgers ord. Frågas inte alls under pass-through | ja | backend-test (1 ListUsage + 1 per namngiven + 1 anonym probe) | Täckt via BFF | Högst 200 konsumenter per sidladdning (MAX_CONSUMERS) | | AdminService | FlowSvg (flödesbilden som SVG, beräknad av holger: RON-grafen + per dörr/repo: anrop i dag och distinkta konsumenter, no consumer vid noll) | ja | ja | öppen¹ (samma läsgrind som /metrics) | Flow-sidan (/flow) — BFF:en frågar med konsolens credential och skickar bilden same-origin på /api/flow.svg (session krävs, viewer-golv) | ja | backend-test | Täckt via BFF | Wasm-koden anropar inte RPC:n själv; bilden ritas som <img> från BFF:en så img-src 'self' håller | | AdminService | BecomeTwin (bootstrap-dörren som gör en låda till tvilling) | ja | nej | admin | — | — | — | Ej lämplig för webb-UI | En bootstrap-handling från xtask, en gång per låda; ingen knapp i en konsol | | AdminService | AdminSnapshot (adminvyn: varje disk och volym med statvfs, tvillingen, tillväxten + journalen, klockan, plugins/monetize, audit, installatörens loggdörr) | ja | ja | admin | Admin-sidan (/admin, flikarna Disks · Twin · Growth · Clock · Plugins / Monetize · Logs) — BFF:en frågar med konsolens credential på /api/admin/snapshot; admin-golv i middleware (ADMIN_READS) OCH i handlern, holger frågas aldrig för en lägre session | ja | backend-test (viewer/operator/utan session nekas, holger ej tillfrågad; admin får svaret) | Täckt via BFF | Wasm-koden anropar inte RPC:n själv; länken visas bara för en admin-session enligt /auth/status, men skyddet är serverns | | AdminService | TwinCsr, IssueTwinCertificate, InstallTwinCertificate (tvillingen över mTLS: nyckel, utfärdande, installation) | ja | nej | admin | — | — | — | Ej lämplig för webb-UI | Parningssteg som installatören/estate-ops kör en gång per låda; adminvyn visar resultatet (certifikatens livslängd) men gör dem inte | | AdminService | Recharge, RechargeStatus, TwinStatus (återladdning av en död main från tvillingen, och lanens två frågor) | ja | nej | admin | — (TwinStatus-uppgifterna syns i adminvyns Twin-flik via AdminSnapshot) | — | — | Ej lämplig för webb-UI | Återladdningen körs av monetize restore-lanen / holger-server recharge, inte från en konsolknapp | | AdminService | FencePrimary (en återladdning stänger den gamla primärens skrivningar) | ja | nej | admin | — | — | — | Ej lämplig för webb-UI | Körs av återladdningslanen (fence_primary), inte från en konsolknapp | | AdminService | ImportIntelBundle, ImportBundle (lådans importdörrar för intel- och uppdaterings-/airgap-bundlar, lane W4: klientströmmar) | ja | nej | Repository Admin eller Security Approver | — (samma kod nås över HTTP POST /-/intel/import, POST /-/bundle/import, inkorgarna och CLI:n) | — | — | CLI/HTTP-yta | En bundle bärs in av operatören; ingen konsolknapp beslutad | | AdminService | Topology (estatets tavla: front, main, tvilling och nedströms, ritad av servern i svg) | ja | ja | admin-läsning (serverns) | Översikten (HOL-UI-FIX): ett kort per låda (front, main, tvilling, nedströms) med serverns tillståndsord, senast hörd, lagg och disk; källorna; lagringen (varje mätt låda); Flow-sidans rad under bilden; vägran visas med serverns kod och ord | ja | enhet (mockserver) | Fullt täckt | Konsolen ritar och avgör inget | | AdminService | SecuritySummary (Security-sidan: gatewayn i holgers ord — kedjan, källor och skannrar, vad som väntar och hålls, vem som läser, synkens signaturer, de senaste säkerhetshändelserna; en sektion per kort) | ja | ja | Admin, Repository Admin, Security Approver eller Auditor (serverns, holger-auth-2 annars) | Security-sidan (/security): ett kort per sektion som servern skickade, raderna som de kom; ingen estate-tavla (den är Översiktens); vägran visas med serverns kod och ord | ja | browser-test (security_page) | Fullt täckt | Konsolen ritar och avgör inget (lane HOL-SEC, raden saknades: HHUNT-3) |
UI ↔ backend capability coverage
Verifierad 2026-08-13, utökad 2026-08-14 (type-to-confirm, skeletons) mot
proto/holger.proto(vendrad, byte-identisk med holger-huvudrepot), runtime-wiringen iserver/lib/src/lib.rs(start_grpc_endpointregistrerar elva tonic-tjänster (åtta alltid, MigrationService endast i ettonline-bygge)) och tjänsteimplementationerna + testerna iserver/lib/src/grpc/services.rs. Källordning: tester → runtime-wiring → implementation → konfiguration → schema → docs.Maskinvaktad:
tests/contract.rsfailar om proton får en service eller RPC utan tabellrad i det här dokumentet (en mening i löptext räcker inte), om en proto-tjänst saknar klient isrc/grpc.rs, om två RPC:er delar namn (matrisen nycklas på namnet), och om en RPC som ingen vy anropar ändå står som "Fullt täckt" — det gapet måste redovisas som gap. Underhålls för hand därutöver."Testad"-nivåer: live = körd mot riktig server i webbläsaren (dev och/eller prod-kedjan över tailnätet); backend = exekverbart backendtest; enhet = nativ enhetstest i UI-repot; — = ej exercerad (skälet står i Åtgärd).
gRPC-tjänster (runtime-registrerade, nåbara genom gRPC-web-dörren)
| Service | Backendfunktion | Runtime-ansluten | Webbsäker | Krävd roll | Nuvarande UI-yta | UI-state komplett | Testad | Status | Åtgärd |
| AdminService | Health (status/version/uptime) | ja | ja | öppen | Topbar-prick (ordet, versionen i title) + Översiktens serverkort | ja | live | Fullt täckt | — |
| AdminService | ListRepositories | ja | ja | öppen¹ | Repolistan (filter/sortering i URL; en grupp visas som group · N members ur is_group/members), pickers, Översikts-sammanfattning |
ja | live | Fullt täckt | — |
| AdminService | ServerProfile (read-only/degraderat läge, writable-antal) | ja | ja | öppen | Översiktens Mode-kort + read-only-varningsbanner | ja | live | Fullt täckt | — |
| AdminService | WhoAmI (subject/metod/effektiv global roll/read-gate) | ja | ja | öppen (introspektion, ekar aldrig credential) | Topbar-identiteten, Översiktens Session-kort, Account-sidan | ja | backend + live | Fullt täckt | Tillagd i denna iteration (proto + server + test + UI) |
| AdminService | Capacity (total/tillgängligt/använt av holger, statvfs över dataroten) | ja | ja | admin | — (ingen admin-sida för lagring finns i konsolen; ingen ny sida skapas utan beslut) | — | — | Ej täckt | Tillagd i holger 4426a12; visas när en admin-lagringsyta beslutas |
| RepositoryService | FetchArtifact (unär) | ja | ja | öppen¹ | Download-knappen | ja | live | Fullt täckt | — |
| RepositoryService | StreamArtifact (server-streaming) | ja | ja | öppen¹ | — (unär används) | — | — | Delvis täckt | Medvetet: webbläsaren buffrar blobben oavsett; unär räcker |
| RepositoryService | ListArtifacts (limit/page_token/name_filter) | ja | ja | öppen¹ | Browse på repo-detaljen; behåller tidigare data under omladdning | ja | live | Fullt täckt | Tomläget avgörs av RepositoryInfo.supports_listing (holger 4426a12): false ⇒ tom lista ≠ tomt repo; true ⇒ repot är tomt. Ingen gissning per repo-typ |
| RepositoryService | PutArtifact | ja | ja | writer | Upload-panelen, gated på writable-flaggan (servern förblir domare) |
ja | live | Fullt täckt | Read-only-repon får förklaring i stället för panel |
| RepositoryService | PutArtifactStream (strömmad uppladdning av stora artefakter; stinky 14) | ja | ja | writer | — (grpc-web strömmar inte klient→server) | — | — | Olämplig | Webbläsarens uppladdning går via PutArtifact; paketverktygen och CLI strömmar |
| ArchiveService | ListArchiveFiles (prefix-filter) | ja | ja | öppen¹ | Arkiv-sektionen på repo-detaljen (syns vid has_archive) |
ja | live | Fullt täckt | Verifierad mot RIKTIGT znippy-arkiv (3 crate-sökvägar, prefix vetra → 2/2) |
| ArchiveService | ArchiveInfo (antal/bytes/sökväg) | ja | ja | öppen¹ | Samma sektion | ja | backend + live | Fullt täckt | Verifieringen HITTADE en backend-bugg (writable-läget svarade nollor) — fixad i holger 906e748 + regressionstest |
| SearchService | Search: name/namespace/version/checksum/path | ja | ja | öppen¹ | Sökvyn (checksum-varningen bevaras) | ja | live | Fullt täckt | Stale-svar ignoreras via generationsräknare |
| SearchService | Search: repositories-begränsning | ja | ja | öppen¹ | Repo-dropdown + "search within this repository" | ja | live | Fullt täckt | — |
| SearchService | Search: properties (PropertyMatch) | ja | ja | öppen¹ | Key/value-filterrader, URL-synkade, chips + reset | ja | live | Fullt täckt | — |
| SearchService | format-axel | — | — | — | — | — | — | Ej runtime-ansluten | Finns inte i proton; att hitta på den vore simulering |
| SbomService | FetchSbom | ja | ja | öppen¹ | Detaljvyns SBOM-sektion (NotFound = normalläge) | ja | live | Fullt täckt | — |
| SbomService | AttachSbom | ja | ja | writer | Samma sektion; refetch efter attach; tidsstämplad | ja | live | Fullt täckt | — |
| PropertyService | GetProperties | ja | ja | öppen¹ | Detaljvyns properties-tabell | ja | live | Fullt täckt | — |
| PropertyService | SetProperty (tomma values = remove) | ja | ja | writer | Editor + per-rad Remove; svarets fulla karta är sanningen | ja | live | Fullt täckt | — |
| PromotionService | PromoteArtifact | ja | ja | admin (mål-repo) | Detaljvyn bakom bekräftelsedialog med type-to-confirm: målrepots namn måste skrivas ut innan knappen armas (from→to, koordinat, seal-once-konsekvens; fokusfälla + fokusåterställning) | ja | enhet + live | Fullt täckt | Grinden live-verifierad mot kringgång: källrepots namn, nästan-rätt och fel skiftläge armar INTE; återöppning nollställer. Dialogens tre vägar verifierade: konsekvens, cancel, vägran ordagrant |
| PromotionService | ListIntakeArtifacts (säkerhetsdashboarden: serverns fem köer med antal, och den öppna köns rader) | ja (supply-chain) |
ja | läsplikt per rad (serverns) | Security: köbrickor + tabell, /security?queue= |
ja | enhet (mockserver) + live i holger | Fullt täckt | Köerna och vilka tillstånd de rymmer är serverns |
| PromotionService | GetArtifactState (tillstånd, historik, röster mot kvorum) | ja (supply-chain) |
ja | läsplikt (serverns) | Security → artefaktvyn: tillstånd, importör, "1 of 2 approvals", historiktabell | ja | enhet (mockserver) | Fullt täckt | — |
| PromotionService | GetArtifactEvidence (skanningsbeviset: hashar, varje skanners utslag och fynd, SBOM-dokumentet, policyns ord) | ja (supply-chain) |
ja | läsplikt (serverns) | Security → artefaktvyn: Integrity, Malware, Vulnerabilities, License, Provenance, SBOM (nedladdning + sammanfattning), Policy | ja | enhet (mockserver) + live i holger | Fullt täckt | — |
| PromotionService | AdvanceArtifact (Approve, Quarantine, Release, Block) | ja (supply-chain) |
ja | plikter (serverns, holger-duty-<n>) |
Security → artefaktvyn: fyra knappar för varje artefakt; Block bakom bekräftelse; vägran visas med serverns kod och ord | ja | enhet (mockserver) | Fullt täckt | Ingen rollogik i konsolen: knapparna är desamma för alla |
| AuditService | GetArtifactTrail (artefaktens spår i hashkedjan, med kedjans utslag) | ja | ja | Auditor eller admin (serverns, holger-audit-10) |
Security → artefaktvyn: Trail-tabellen; vägran visas med serverns kod och ord | ja | enhet (mockserver) | Fullt täckt | — |
| AuditService | VerifyAuditChain (hela kedjan, första brottet) | ja | ja | Auditor eller admin | — | — | — | Endast CLI | Kedjans utslag syns i trail-svaret (chain_intact, chain_summary); en egen knapp får vänta |
| PromotionService | Lineage/withdrawal/bundles/staging | delvis (lokal motor) | nej (ingen gRPC) | filsystem | — | — | — | Endast CLI | holger-server promote …; withdrawal är en append-only statusändring — får UI-yta först med ett typat API |
| PromotionService | ListDependencySets, GetDependencySet, ApproveDependencySet, RefuseDependencySet (beroendemängderna: en pulls hela closure som EN post, med medlemmar, röster och mängdens revision, SEC-REVIEW D4) |
ja | ja | Security Approver (rösta), läsare enligt plikt | Security-sidan (/security, kortet Dependency sets) — konsolen läser GET /-/intake/sets och skickar `POST /-/intake/set/approve |
refuse?id=&revision=&reason=med den revision kortet visade; holgers 409holger-depset-4visas med holgers ord. **Ingen klient** isrc/grpc.rs` (samma kod nås över HTTP-dörrarna) |
ja | enhet (depsets) + browser (set_votes) |
Täckt via HTTP |
| ReplicationService | Replicate preview/execute + räknare | ja | ja | admin | Repositories → Replicate (förr Operations-vyn): preview-först, Execute låst till samma par, alla räknare separata, incomplete = röd banner, tidsstämplad | ja | live | Fullt täckt | Ok-svar med partiella fel presenteras aldrig som framgång |
| MigrationService | Discover (plan + refusals + delad dry-run-rapport) | ja (endast online-bygge) |
ja | admin (serverbred, fail-closed) | Repositories → Migrate in (förr Operations → Migrate): formuläret + repotabellen med kryssrutor, disposition, assets/bytes; rapporten renderas av SERVERNS report-fält (samma renderare som CLI:ns --dry-run) |
ja | enhet | Fullt täckt | Läser inget artefaktinnehåll och skriver ingenting |
| MigrationService | Start (jobb-id direkt, plan vägrad INNAN jobbet finns) | ja (endast online-bygge) |
ja | admin (serverbred, fail-closed) | Start-knappen på det valda urvalet: hela registret = ett jobb, delmängd = ett jobb per repo i tur och ordning (wire-kontraktet har "allt" och "detta ena", inte "dessa fem") | ja | enhet | Fullt täckt | skip_digest_verification lämnas false — nollvärdet är det säkra |
| MigrationService | Watch (server-streaming progress) | ja (endast online-bygge) |
ja | admin (serverbred, fail-closed) | Progress-tabellen: per repo done/skipped/failed/total/bytes + procent; job-loggen | ja | enhet | Fullt täckt | En sen watcher får senaste raden per repo först — reconnect är samma väg |
| MigrationService | Cancel | ja (endast online-bygge) |
ja | admin (serverbred, fail-closed) | Cancel-knappen, armad bara medan ett jobb löper; stoppar även kön av följande jobb | ja | enhet | Fullt täckt | Avbrutet jobb renderas som "cancelled — a partial migration is on disk", aldrig som framgång |
| MigrationService | Skapa målrepo | nej — finns inte, kan inte finnas | — | — | Sidan ERBJUDER det inte: en create-rad går inte att kryssa i, den visar RON-deklarationen att klistra in (serverns declaration-fält, renderat av traits::migrate::ron_declaration) |
ja | enhet | Ej runtime-ansluten | FastRoutes byggs ur konfigurationen vid boot och är immutabel processen ut. Flödet är Discover → deklarera → starta om → Start, och det är sidans synliga mitt |
| AuditService | QueryAudit (alla poster: aktör, repo, artefaktprefix, handling, källadress, status, tid; sidvis; ur Arrow-indexet) | ja | ja | Auditor eller admin | — (Ingen klient i src/grpc.rs) |
— | — | Endast CLI | holger-cli audit query; revisionsläsning har ingen vy ännu (HOL-AUDIT 2026-10-30) |
| AuditService | AggregateAudit (antal och bytes per repo, handling, dag, aktör, klient, status) | ja | ja | Auditor eller admin | — (Ingen klient i src/grpc.rs) |
— | — | Endast CLI | holger-cli audit aggregate; flödesbildens räknare (FlowSvg) läser samma aggregat på servern |
| AuditService | ExportAudit (valda poster som en Arrow IPC-fil) | ja | ja | Auditor eller admin | — (Ingen klient i src/grpc.rs) |
— | — | Endast CLI | holger-cli audit export --out |
| AuditService | QueryDownloads (vad laddade C ner: per ident, repo och tid; stinky SB #19) | ja | ja | admin | — (Ingen klient i src/grpc.rs) |
— | — | Endast CLI | Samma medvetna gap som QueryAudit; HTTP /-/audit/downloads finns hos holger |
| UsageService | ReadUsage | ja (alla byggen) | ja | läsare på repot | Repodetaljens Disk-panel och My plan (/plan): disk_bytes mot taket (caps) som "1.0 GB of 5.0 GB" + mätare |
ja | enhet (mockserver, mine) |
Fullt täckt | Konsolen räknar inget själv |
| RoomService | Room (länken till ONE-butiken för mer utrymme, med biljett för en admin) | ja | ja | läsare på repot | Repodetaljens More room-panel och My plan (/plan, "More room in the shop"); en vägran visas med serverns ord |
ja | enhet (mockserver, mine) |
Fullt täckt | Privat Holger-beställning och förnyelsesidan är ONE-butikens (lane P1) |
| AccountService | MyRepositories (personens repon: ägaren ser sina, en admin alla utom systemrepon; formaten servern gör; klientuppsättning för cargo, pip, npm, maven, oci, raw; planens läge: paid/grace/suspended/retention/lapsed, paid until) | ja | ja | öppen (anonym = inga repon, "sign in") | My repositories (/mine, kort per repo med klientuppsättning och kopieringsknapp) och My plan (/plan, planens läge och ord) |
ja | enhet (mockserver, mine) + holger-integrationstest |
Fullt täckt | Ägare, behörighet och format är serverns; konsolen visar svaren |
| AccountService | CreateRepository (ett privat repo som en admin gör, ägt av admin, läsningar kräver credential från första anropet) | ja | ja | admin | My repositories: formuläret (namn + ett av serverns format), ett anrop, serverns ord eller vägran med kod (holger-account-1..4) |
ja | enhet (mockserver, mine) + holger-integrationstest |
Fullt täckt | — |
| TokenService | Mint, List, Revoke (repotoken för pakethanterare, lane P3: hemligheten visas en gång) | ja (när lane P3 landat) | ja | inloggad person (Mint: stepped-up passkey) | My tokens (/tokens): formulär (etikett, repon, scope, dagar), hemligheten en gång med kopieringsknapp, tabell med Revoke för en levande token |
ja | enhet (mockserver, mine) |
Täckt mot P3:s kontrakt (stub tills P3 landar) | proto/holger-token.proto är P3:s utkast; tests/proto_is_holgers.rs kräver holgers kopia så fort holger committar filen |
¹ "öppen" = airgap-mirror-posturen (läsning utan credential). Med require_auth_for_reads i serverns RON gäller reader-golvet — samma anrop, samma UI; konsolen visar Unauthenticated som "authentication required" med login-länk (FailBox-klassificeringen).
Autentisering och säkerhet
| Service | Backendfunktion | Runtime-ansluten | Webbsäker | Krävd roll | Nuvarande UI-yta | UI-state komplett | Testad | Status | Åtgärd |
| (transport) | Bearer-token (StaticToken/API-nyckel) | ja | ja | — | Account: token-paste (maskerad), interceptor | ja | live | Fullt täckt | — |
| (transport) | OIDC access-token-validering (JWKS offline/userinfo) | ja (feature-pinnad per tier) | ja | — | Samma tokenlager | ja | live (mock-IdP) | Fullt täckt | — |
| (klient) | OIDC authorization-code + PKCE | ja | ja | — | Account: SSO-formuläret (oidc.rs) |
ja | live (mock-IdP, inkl. förfalskad callback) | Fullt täckt | — |
| (transport) | mTLS-klientcert | ja (transportnivå) | delvis | — | — | — | — | Ej lämplig för webb-UI | Webbläsaren/OS:et äger certvalet; WhoAmI rapporterar dock en mTLS-identitet korrekt |
| (backend) | WebAuthn | nej (medvetet ej dispatch-ansluten) | — | — | — | — | — | Ej runtime-ansluten | Rörs inte (låst av auth_ship_small-länkrevisionen) |
| (policy) | RBAC-avslag/quarantine/policyfel | ja | ja | — | Ordagrant i FailBox/mutationsstatus | ja | live | Fullt täckt | Ingen klient-RBAC; quarantine får inget existensorakel |
Utan webbsäkert API — ärligt klassificerat
| Backendfunktion | Runtime-ansluten | Åtkomstväg | Status | Motivering |
| Delete/raw-radering | ja (native-HTTP-dörren) | DELETE /{repo}/{path} med SHA-256-verifiering, egen port |
Ej lämplig för webb | Ingen gRPC-RPC; native-dörren är en annan origin för stock-klienter. Typat delete-API = medvetet framtida beslut (Kräver backend-API) |
| Retention/GC | ja (CLI-verb) | holger-server retention … (gated dry-run) |
Endast CLI | Destruktiv operation utan gRPC-yta; den lokala vägen är avsiktlig |
| Audit-läsning/verify | ja (CLI-verb) | holger-server audit verify, Arrow-IPC-segment på disk |
Endast CLI | Append-only-loggen exponeras inte över nätverket; mutationsresultat i UI bär tidsstämpel för manuell korrelation mot segmenten |
| Secure-update: bundle/scrub/backup/restore | ja (CLI-verb) | holger-server bundle/scrub/backup … |
Endast CLI | Medvetet offline/lokalt (airgap-designen) |
| Promotion via lokal CLI | ja | holger-server promote --from --to |
Endast CLI | In-process-vägen, gated av filrättigheter |
| Provisionering/dev-pair/tjänsteinstallation | ja (CLI) | holger-server provision/service … |
Startup-konfiguration | Serverinstallation är inte en webbläsaråtgärd |
| Agent/airgap-överföring | ja (egen binär, internetsidan) | holger-agent |
Ej lämplig för webb | Körs på andra sidan airgapet; ingen server-API-yta |
| Quarantine-gate | ja (env vid serve) | HOLGER_QUARANTINE_PROPERTY |
Startup-konfiguration | UI visar avslag ordagrant utan existensorakel |
| Jobbstatus/job ledger | nej | finns inte | Ej runtime-ansluten | Ingen platshållarsida skapas |
| Repository-konfiguration (RON-grafen) | ja (startup) | RON-fil vid boot | Startup-konfiguration | Ingen mutations-API; degraderat läge syns via ServerProfile/ListRepositories. Per-repo "senaste fel" saknar API — Kräver backend-API om det ska visas |
Väntetillstånd och inaktuella data
Tabellformade väntan renderar layoutbevarande skeletons (components/skeleton.rs): aria-hidden på platshållarna, EN visuellt dold live-region som säger vad som laddas, och animationen bortkopplad under prefers-reduced-motion. Data som laddas om ligger kvar men dimmas (.stale) i stället för att ersättas av en spinner — inaktuella rader ska läsas som inaktuella, inte som aktuella. Små inline-väntan (SBOM, properties, korten på Översikt) behåller textvarianten; en skeleton där skulle antyda en form som inte kommer.
Adversariell granskning 2026-08-14
Fem oberoende linser (honesty, state, a11y, security, correctness) granskade konsolen; varje fynd prövades av en skeptiker med uppgift att motbevisa det. Sju fynd överlevde och är åtgärdade — samtliga verifierade live efter fix:
| Fynd | Åtgärd | Verifierat |
| Misslyckad artefaktlistning lämnade förra frågans rader kvar, odimmade, med "N shown" | Färsk laddning som avslås tömmer listan; FailBox står ensam | 100 rader → 0 + "failed to list: not found" |
| Repo-browse saknade stale-vakt (repo-byte, filter och Load-more kunde landa i fel ordning) | Samma generationsräknare som sökningen | kompilerad + browse oförändrad i drift |
| Artefaktfakta svalde felet: ett avslag renderades som "—" (påstådd frånvaro) | Result med tre lägen; avslag visar serverns ordagranna text |
okänt repo → "unknown" + serverns mening |
| Sökningens nollställning ogiltigförklarade inte pågående sökning | Generationen bumpas före tidiga returen | 2 träffar → 0, inget hängande "searching…" |
| IdP:ns avslag i OIDC-callbacken sväljs; engångshemligheten levde vidare | Avslaget visas ordagrant; verifier+state konsumeras oavsett utgång | banner + tomma nycklar |
--muted klarade inte 4.5:1 på NÅGON yta (4.05/3.73/3.50/3.23) |
#8b98ad — 5.26–6.59:1 överallt |
egen kontrasträkning + computed style |
| README/quadlet dokumenterade en publiceringsväg UTAN CSP (markören är en kommentar) | publish.sh är enda dokumenterade vägen; kedjekontrollen failar utan CSP-header/fel hash |
verify-chain.sh grön, alla nio kontroller |
Tre fynd motbevisades och är INTE åtgärdade: att artefaktdetaljens övriga anrop redan visar avslaget (delvis sant — men inte för feltypat repo, därav fixen ovan), att repo→repo-ometikettering saknar nåbar väg (sant: ingen länk finns mellan två repo-sidor — fixen behövdes ändå för det nåbara filter-fallet), och att scrollbara block skulle sakna tangentbordsåtkomst (fel: <pre> utan fokuserbara barn får UA-fokus, och tabellerna innehåller länkar/knappar).
Adversariell granskning, runda två (2026-08-14, mot holger 826feae)
Samma fem linser plus en sjätte med uppgift att attackera de sju fixarna. Elva fynd överlevde skeptikern, men fem av dem var samma defekt sedd av fem oberoende linser — sex distinkta fel, alla åtgärdade och live-verifierade:
| Fynd | Åtgärd | Verifierat |
| Fix 1 gjordes bara på halva ytan: en avslagen SÖKNING lämnade förra frågans tabeller kvar, odimmade, under den nya frågans chips (funnen av 5 linser, en satte HIGH) | results.set(None) på felgrenen — samma regel som browse |
transportfel injicerat: 2 rader → 0, inga "Artifacts (n)"-rubriker, felet ensamt |
.stale-dimningen upphävde fix 6: group-opacity komponerar TEXTEN → th 2.58:1, länkar 2.91:1 (under både 4.5 och 3.0) |
dimningen ersatt av en "refreshing…"-ribba + aria-busy; färgerna orörda |
egen räkning: 5.71 / 6.98 / 16.19 / 5.99 — allt över AA; opacity mätt till 1 under laddning |
| Fix 3 ofullständig: "—" påstod frånvaro även när koordinaten låg bortom första sidan | fyra lägen (Found / Absent / Undetermined / fel) — "—" bara när sidan var komplett |
Found "8 B", Absent "—" utan fel, fel → "unknown" + serverns mening |
| Avslagen property-SKRIVNING skrev över LÄS-tillståndet och etiketterades som misslyckad hämtning; ingen busy-vakt | eget skrivtillstånd; listan står kvar; knappar låsta under skrivning | anonym skrivning: listan ["stage"] intakt, "property write refused: …", och två extra klick gav ETT anrop |
publish.sh körde chmod -R a+rX över hela publiceringskatalogen — datalagret, promote-seglen och audit-segmenten ligger under den |
chmod skopad till dist + nginx.conf (det quadleten faktiskt monterar) |
282 världsläsbara filer → 0; store drwxr-x---; nginx serverar fortsatt 200 |
| Trunkeringsvarningarna (sök + replikering) saknade live-region | role="alert", som de övriga banners |
attributet i källan; inte live-exercerat (kräver >200 träffar) |
Ett fynd motbevisades (properties-hämtningen skulle sakna generationsvakt).
Inte live-exercerat, medvetet redovisat: Facts::Undetermined kan inte nås med nuvarande data — faktafrågan filtrerar på det exakta artefaktnamnet, som matchar en enda post; läget är kompilatorkontrollerat och kodgranskat, inte kört. Detsamma gäller trunkeringsbannern (kräver >200 sökträffar).
Verifieringsnoteringar
- Åtta tjänster registreras i
start_grpc_endpoint— kontrollerat mot koden;tests/contract.rslåser antalet och kräver en klient per tjänst isrc/grpc.rs(gapet var verkligt: ArchiveService saknade klient). - Tom
ListArtifactsär INTE bevis på tomt repo (holger-repots ai-context varnar uttryckligen); tomläget formuleras därefter, och "inga filterträffar" är ett eget tomläge skiljt från "inga repositories". - Arkiv-vyn fullverifierad mot riktigt arkiv: writable rust-znippy-repo seedad via konsolens egen upload; badge-övergång,
ArchiveInfo(3 files · 54 B · crates-dev, exakt), fillistning + prefix-filter — och verifieringen hittade en riktig backend-bugg (fixad i holger906e748med regressionstestetwritable_repo_archive_info_reports_live_stats). - Nativ enhetstestyta: kratsen är
cfg(target_arch = "wasm32")så när som påsrc/util.rs, så vyernas RENA beslut ligger där ochcargo testtäcker dem utan webbläsarharness: sökens och repolistans adressbyggen (escaping, chip-borttagning, sorteringsväxling), marketplace-statusens rubrik/ton/banner, nedladdningsnamnet och property-värdena på detaljvyn, replikeringens preview-grind, gRPC-dörrens bas-URL och miljöchipet, FailBox-klassificeringen (total över alla 17 statuskoder) samt PKCE-delarna: base64url (RFC 4648 §5, opaddad), discovery-URL, redirect-URI, authorize-parametrarna (S256, och CHALLENGE — aldrig verifiern) och token-formuläret (verifier, ingen client secret). - WhoAmI: introspektion genom SAMMA
auth::validate_requestsom gaterna (ingen tvilling); ogiltig credential rapporteras som anonym, aldrig fel; backendtestetwho_am_i_reports_anonymous_and_mapped_roleslåser formen.