workflow: svcauth, tenantregistryclient aus common v0.1.0
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Failing after 11s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Failing after 23s
CI / Core-Modul (Build/Vet/Test) (push) Failing after 1m6s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Successful in 3s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Successful in 4s
CI / Web (dms-browser) (push) Failing after 1m31s
CI / Web (pdf-viewer) (push) Failing after 1m3s
CI / Web (shl) (push) Failing after 14s
Supply-Chain-Scan (Go) / govulncheck (push) Failing after 4m11s
Workflow-Schnittstellen-Vertragstests / contract-tests (push) Failing after 41s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Successful in 7s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (pull_request) Successful in 8s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Failing after 30s
CI / Web (dms-browser) (pull_request) Failing after 1m24s
CI / Web (pdf-viewer) (pull_request) Failing after 57s
CI / Core-Modul (Build/Vet/Test) (pull_request) Failing after 11m29s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Failing after 3m26s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Failing after 1m57s
Workflow-Schnittstellen-Vertragstests / contract-tests (pull_request) Failing after 57s
Workflow-Pflichttest-Gate / pflichttest-gate (pull_request) Failing after 1m13s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Successful in 10m30s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Successful in 10m25s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Successful in 9m47s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Failing after 3s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Failing after 3s
DB-Integrationstests / db-tests (pull_request) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Failing after 11s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Failing after 23s
CI / Core-Modul (Build/Vet/Test) (push) Failing after 1m6s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Successful in 3s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Successful in 4s
CI / Web (dms-browser) (push) Failing after 1m31s
CI / Web (pdf-viewer) (push) Failing after 1m3s
CI / Web (shl) (push) Failing after 14s
Supply-Chain-Scan (Go) / govulncheck (push) Failing after 4m11s
Workflow-Schnittstellen-Vertragstests / contract-tests (push) Failing after 41s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Successful in 7s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (pull_request) Successful in 8s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Failing after 30s
CI / Web (dms-browser) (pull_request) Failing after 1m24s
CI / Web (pdf-viewer) (pull_request) Failing after 57s
CI / Core-Modul (Build/Vet/Test) (pull_request) Failing after 11m29s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Failing after 3m26s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Failing after 1m57s
Workflow-Schnittstellen-Vertragstests / contract-tests (pull_request) Failing after 57s
Workflow-Pflichttest-Gate / pflichttest-gate (pull_request) Failing after 1m13s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Successful in 10m30s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Successful in 10m25s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Successful in 9m47s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Failing after 3s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Failing after 3s
DB-Integrationstests / db-tests (pull_request) Canceled after 0s
Das Pflichttest-Gate von workflow verweist nicht mehr auf die geloeschten Pakete (common hat ein eigenes Gate). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
184a219c8a
commit
eaffcaf885
15 files changed
+36
-102
No files matched your search
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"gitea.perlbach24.de/scripte/nexarch/common/tenantregistryclient"
|
||||
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/approval"
|
||||
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/approvalapi"
|
||||
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/backchannel"
|
||||
@@ -33,7 +34,6 @@ import (
|
||||
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/routingruleapi"
|
||||
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/routingsuggestclient"
|
||||
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/task"
|
||||
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/tenantregistryclient"
|
||||
)
|
||||
|
||||
func requireEnv(name string) string {
|
||||
|
||||
+4
-1
@@ -2,7 +2,10 @@ module gitea.perlbach24.de/scripte/nexarch/workflow
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require github.com/jackc/pgx/v5 v5.9.2
|
||||
require (
|
||||
gitea.perlbach24.de/scripte/nexarch/common v0.1.0
|
||||
github.com/jackc/pgx/v5 v5.9.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
gitea.perlbach24.de/scripte/nexarch/common v0.1.0 h1:biNzFr2LOMZC7b1leY3smQtrMmSMp6IW80OvR4LSjLY=
|
||||
gitea.perlbach24.de/scripte/nexarch/common v0.1.0/go.mod h1:CiEImG++QMt1xZqSMeDJhPiB7sfWTLZOwjS6OY/Iguc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
||||
@@ -302,4 +302,3 @@ func TestForObject_RegistryTransportError_FailsClosed(t *testing.T) {
|
||||
t.Fatalf("erwartet ErrForbidden bei registry-transportfehler (fail-closed), bekommen %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,10 @@ type Detail struct {
|
||||
type KanbanColumn string
|
||||
|
||||
const (
|
||||
ColumnOpen KanbanColumn = "open"
|
||||
ColumnThisWeek KanbanColumn = "this_week"
|
||||
ColumnOverdue KanbanColumn = "overdue"
|
||||
ColumnDone KanbanColumn = "done"
|
||||
ColumnOpen KanbanColumn = "open"
|
||||
ColumnThisWeek KanbanColumn = "this_week"
|
||||
ColumnOverdue KanbanColumn = "overdue"
|
||||
ColumnDone KanbanColumn = "done"
|
||||
)
|
||||
|
||||
// KanbanItem ist eine Wiedervorlage mitsamt der Spalte, in der sie gerade
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
||||
@@ -174,13 +174,13 @@ func (d *Dispatcher) Dispatch(ctx context.Context) (int, error) {
|
||||
// dasselbe Ereignis reserviert nicht erneut und legt daher auch
|
||||
// keine zweite Aufgabe an (Akzeptanzkriterium 2).
|
||||
// 2. Aufgabe/Genehmigung wird angelegt.
|
||||
// 3a. Erfolg: die Reservierung wird mit der erzeugten Objekt-ID
|
||||
// bestaetigt und module_events als verarbeitet markiert.
|
||||
// 3b. Fehlschlag: die Reservierung wird wieder geloescht, damit ein
|
||||
// spaeterer Dispatch-Lauf es erneut versuchen kann -- das
|
||||
// verbleibende Restrisiko ist ein Absturz exakt zwischen 2 und 3a,
|
||||
// das Ereignis bliebe dann dauerhaft reserviert ohne erzeugtes
|
||||
// Objekt (dokumentiert in ENG-09-PRUEFPROTOKOLL.md).
|
||||
// 3a. Erfolg: die Reservierung wird mit der erzeugten Objekt-ID
|
||||
// bestaetigt und module_events als verarbeitet markiert.
|
||||
// 3b. Fehlschlag: die Reservierung wird wieder geloescht, damit ein
|
||||
// spaeterer Dispatch-Lauf es erneut versuchen kann -- das
|
||||
// verbleibende Restrisiko ist ein Absturz exakt zwischen 2 und 3a,
|
||||
// das Ereignis bliebe dann dauerhaft reserviert ohne erzeugtes
|
||||
// Objekt (dokumentiert in ENG-09-PRUEFPROTOKOLL.md).
|
||||
func (d *Dispatcher) dispatchOne(ctx context.Context, e pendingEvent) (bool, error) {
|
||||
rule, ok, err := d.rules.ruleFor(ctx, d.pool, e.ModuleName, e.ObjectType, e.Trigger)
|
||||
if err != nil {
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/svcauth"
|
||||
"gitea.perlbach24.de/scripte/nexarch/common/svcauth"
|
||||
)
|
||||
|
||||
// TenantVerifier prueft einen vom aufrufenden Modul mitgelieferten
|
||||
|
||||
@@ -17,9 +17,7 @@ import (
|
||||
// sensitivePathPatterns beschreibt die Bereiche aus
|
||||
// workflow/docs/TESTSTRATEGIE.md Abschnitt 4.
|
||||
var sensitivePathPatterns = []*regexp.Regexp{
|
||||
regexp.MustCompile(`(^|/)workflow/internal/svcauth/`),
|
||||
regexp.MustCompile(`(^|/)workflow/internal/moduleadapter/`),
|
||||
regexp.MustCompile(`(^|/)workflow/internal/tenantregistryclient/`),
|
||||
regexp.MustCompile(`(^|/)workflow/internal/backchannel/`),
|
||||
regexp.MustCompile(`(^|/)workflow/internal/backchannelapi/`),
|
||||
regexp.MustCompile(`(^|/)workflow/internal/dualcheck/`),
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
// Negativtest des Gates selbst (QA-01 Pruefung 1): ein Diff mit
|
||||
// geaenderter workflow/internal/svcauth/svcauth.go ohne begleitende
|
||||
// geaenderter workflow/internal/moduleadapter/moduleadapter.go ohne begleitende
|
||||
// Testdatei muss als Verstoss erkannt werden.
|
||||
package pflichttestgate
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCheckDiff_FlagsSensitiveChangeWithoutTest(t *testing.T) {
|
||||
violations := CheckDiff([]string{"workflow/internal/svcauth/svcauth.go"})
|
||||
violations := CheckDiff([]string{"workflow/internal/moduleadapter/moduleadapter.go"})
|
||||
if len(violations) != 1 {
|
||||
t.Fatalf("erwartet genau 1 verstoss, habe %d: %+v", len(violations), violations)
|
||||
}
|
||||
if violations[0].Package != "workflow/internal/svcauth" {
|
||||
if violations[0].Package != "workflow/internal/moduleadapter" {
|
||||
t.Fatalf("falsches package gemeldet: %+v", violations[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckDiff_PassesWhenTestFileAccompanies(t *testing.T) {
|
||||
violations := CheckDiff([]string{
|
||||
"workflow/internal/svcauth/svcauth.go",
|
||||
"workflow/internal/svcauth/svcauth_test.go",
|
||||
"workflow/internal/moduleadapter/moduleadapter.go",
|
||||
"workflow/internal/moduleadapter/moduleadapter_test.go",
|
||||
})
|
||||
if len(violations) != 0 {
|
||||
t.Fatalf("erwartet keine verstoesse, habe: %+v", violations)
|
||||
@@ -34,9 +34,7 @@ func TestCheckDiff_IgnoresNonSensitivePaths(t *testing.T) {
|
||||
|
||||
func TestCheckDiff_CoversAllSensitivePackages(t *testing.T) {
|
||||
files := []string{
|
||||
"workflow/internal/svcauth/x.go",
|
||||
"workflow/internal/moduleadapter/x.go",
|
||||
"workflow/internal/tenantregistryclient/x.go",
|
||||
"workflow/internal/backchannel/x.go",
|
||||
"workflow/internal/backchannelapi/x.go",
|
||||
"workflow/internal/dualcheck/x.go",
|
||||
|
||||
@@ -19,12 +19,12 @@ import (
|
||||
// Decision ist das Ergebnis einer Ausfuehrung: entweder eine passende Regel
|
||||
// mit ihrer Aktion, oder keine Regel (Klaerungskorb).
|
||||
type Decision struct {
|
||||
Matched bool
|
||||
RuleID string
|
||||
RuleName string
|
||||
Action routingrule.Action
|
||||
InBasket bool
|
||||
BasketID string
|
||||
Matched bool
|
||||
RuleID string
|
||||
RuleName string
|
||||
Action routingrule.Action
|
||||
InBasket bool
|
||||
BasketID string
|
||||
}
|
||||
|
||||
type Engine struct {
|
||||
|
||||
@@ -64,8 +64,8 @@ func (s *Server) handleList(w http.ResponseWriter, r *http.Request, _ string) {
|
||||
}
|
||||
|
||||
type ruleInput struct {
|
||||
Name string `json:"name"`
|
||||
Priority int `json:"priority"`
|
||||
Name string `json:"name"`
|
||||
Priority int `json:"priority"`
|
||||
Conditions []routingrule.Condition `json:"conditions"`
|
||||
Actions []routingrule.Action `json:"actions"`
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ import (
|
||||
// TestCase ist ein Objekt aus dem Testkorpus, optional mit einer erwarteten
|
||||
// Regel-ID (leer = "keine Regel soll greifen").
|
||||
type TestCase struct {
|
||||
Label string
|
||||
Object map[string]any
|
||||
ExpectedRuleID string
|
||||
Label string
|
||||
Object map[string]any
|
||||
ExpectedRuleID string
|
||||
}
|
||||
|
||||
// Result ist das Simulationsergebnis fuer einen TestCase: tatsaechliche
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// Package svcauth vergleicht Service-Token in konstanter Zeit (Muster aus
|
||||
// archive/internal/svcauth, Lehre aus RET-14/F-08: ohne diesen Schutz
|
||||
// beim ersten Entwurf des Adapters einbauen statt nachzuruesten).
|
||||
package svcauth
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
)
|
||||
|
||||
// Equal vergleicht die SHA-256-Werte beider Eingaben in konstanter Zeit.
|
||||
// Ein leeres erwartetes Token stimmt nie.
|
||||
func Equal(got, want string) bool {
|
||||
if want == "" {
|
||||
return false
|
||||
}
|
||||
g, w := sha256.Sum256([]byte(got)), sha256.Sum256([]byte(want))
|
||||
return subtle.ConstantTimeCompare(g[:], w[:]) == 1
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// Package tenantregistryclient ist ein schlanker HTTP-Client fuer Core TEN-01
|
||||
// (Tenant-Registry); Workflow ist ein eigenes Go-Modul und kann Cores Pakete
|
||||
// nicht importieren. Gleiches Muster wie dms/internal/tenantregistryclient
|
||||
// und archive/internal/tenantregistryclient.
|
||||
package tenantregistryclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
BaseURL string
|
||||
ServiceToken string
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
func New(baseURL, serviceToken string) *Client {
|
||||
return &Client{BaseURL: baseURL, ServiceToken: serviceToken, HTTPClient: &http.Client{Timeout: 10 * time.Second}}
|
||||
}
|
||||
|
||||
// VerifyTenant fragt Core, ob tenantSlug als Tenant gefuehrt wird. Transport-
|
||||
// und Serverfehler kommen als Fehler zurueck, nie als "gueltig": der Aufrufer
|
||||
// muss fail-closed reagieren.
|
||||
func (c *Client) VerifyTenant(ctx context.Context, tenantSlug string) (bool, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.BaseURL+"/tenants/"+url.PathEscape(tenantSlug), nil)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("tenantregistryclient: request bauen: %w", err)
|
||||
}
|
||||
req.Header.Set("X-Service-Token", c.ServiceToken)
|
||||
resp, err := c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("tenantregistryclient: aufruf fehlgeschlagen: %w", err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
switch resp.StatusCode {
|
||||
case http.StatusOK:
|
||||
return true, nil
|
||||
case http.StatusNotFound:
|
||||
return false, nil
|
||||
default:
|
||||
return false, fmt.Errorf("tenantregistryclient: unerwarteter status %d", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user