Skip to content

Architecture

CodeScoring.Save uses a microservice architecture. Backend API and authentication / authorization are split into separate services: Save API service and cs-auth (Auth/RBAC service).

Technology Stack

  • Development language: Go 1.25+.
  • Metadata storage: PostgreSQL 14+ (recommended for production) or SQLite 3.x.
  • Object storage: S3-compatible storage (MinIO, AWS S3, Yandex Object Storage) or local file system.
  • Authentication: RSA-2048 JWT with JWKS, issued by cs-auth and validated locally by Save through the public key.

Architecture Diagram

flowchart TB
    UI["Web UI · React"]
    PM["Package managers<br/>npm · mvn · docker · nuget · pypi · go"]
    LB["Load Balancer / Ingress"]

    SAVE["<b>Save API service</b><br/>stateless · pods 1..N"]
    AUTH["<b>cs-auth</b> (Auth / RBAC)<br/>stateless · pods 1..N<br/>shared RSA key"]

    DB[("<b>Metadata DB</b><br/>see note below")]
    OBJ[("<b>Object Storage</b><br/>S3-compatible / local FS")]

    UI --> LB
    PM --> LB
    LB --> SAVE
    LB -- "/v2/token (Docker auth flow)" --> AUTH

    SAVE -- "action authorization · JWKS · audit events" --> AUTH
    SAVE --> DB
    SAVE --> OBJ
    AUTH --> DB

Database schema

In a PostgreSQL deployment, both services can share one database instance and one schema; data is separated by table name prefixes. In a SQLite deployment, each service uses a separate database file.

System Components

Save API service

The main backend service that processes incoming requests to repositories and the administrative API.

Functions:

  • Processing HTTP/HTTPS requests from package managers and the web interface.
  • Token validation and integration with the dedicated Auth/RBAC service.
  • Routing requests to the storage backend.
  • Integration with CodeScoring.OSA through OSA Proxy for artifact scanning when downloads are routed through the proxy.
  • Applying security policies and cleanup policies.
  • Structured logging and Prometheus metrics export.

Technical characteristics:

  • Stateless architecture for horizontal scaling.
  • Graceful shutdown during updates.
  • Health checks for Kubernetes.

Auth/RBAC service

A dedicated authentication and authorization service deployed separately from Save API service.

Functions:

  • Authentication of users and service accounts.
  • Issuing and refreshing JWT tokens (RSA-2048, alg=RS256).
  • Managing roles and permissions at global / project / repository levels.
  • Managing API keys, robot accounts, and project membership.
  • Audit of access-related and system-wide operations.
  • Internal API for interaction with Save API service.
  • OCI Distribution Spec token endpoint for Docker / Helm / oras clients.

Technical characteristics:

  • Separate codebase and separate entry point.
  • Dedicated PostgreSQL schema in a shared database instance, or a separate SQLite file.
  • Horizontal scaling independently from Save API service.
  • Required scaling condition: all replicas must share the same RSA key for signing JWT tokens.

Storage Backend

Artifact storage subsystem:

  • Metadata Store — PostgreSQL or SQLite for metadata.
  • Blob Store — object storage for artifacts: S3-compatible storage or file system.

Operations: storing and retrieving artifacts, version management, checksum generation.

Background Workers

Background processes for deferred tasks:

  • Cleanup policies — scheduled removal of outdated artifacts.
  • Background metadata operations.
  • Asynchronous delivery of audit events to cs-auth.

Web UI

Web interface for managing projects, repositories, artifacts, and access settings. Module capabilities are described on the Functional characteristics page.

Service Interaction

  • External clients (Web UI and package managers) access only Save API service through ingress; cs-auth is not exposed outside the cluster.
  • Save API service delegates authentication, role checks, and token issuing to Auth/RBAC service.
  • Both services can use separate or shared PostgreSQL instances, but they work in separate schemas/databases.
  • Save API service works directly with metadata store and object storage; cs-auth works only with metadata store and has no access to object storage.
  • Save calls cs-auth in several cases:
    • Proxying part of the administrative API — Save forwards requests without processing them itself.
    • Checking credentials that are not present in the local pod cache — Basic Auth, API key, NuGet API key, NPM token, Docker token.
    • Sending audit events — one event log for all services.
  • All internal endpoints are additionally protected by a shared secret.
  • On the hot path, Save validates Bearer JWT locally using a cached JWKS public RSA key without a network call to cs-auth.

Data Model

Main Entities

Project

- ID
- Name
- Description
- Owner
- Created/Updated timestamps

Repository

- ID
- Project ID
- Name
- Type (proxy/hosted)
- Format (maven, npm, docker, nuget, pypi, go, raw)
- Configuration
- Storage Backend
- Cleanup Policies
- Created/Updated timestamps

Artifact

- ID
- Repository ID
- Group/Namespace
- Name
- Version
- Format-specific metadata
- Size
- Checksums (MD5, SHA1, SHA256)
- Upload date
- Last accessed

User

- ID
- Username
- DisplayName
- Email
- PasswordHash (bcrypt)
- IsActive
- AuthSource   (local / ldap / oidc)
- LastLoginAt
- Created/Updated timestamps

Role / Robot account

- ID
- Name
- Description
- Permissions (global / project / repository scopes)
- IsAdmin
- IsSystem
- API keys (only for robot accounts)
- Created/Updated timestamps

APIKey

- ID
- UserID            (FK to user with IsService=true)
- KeyPrefix         (first 12 hex characters of the plaintext key, used for O(1) lookup)
- KeyHash           (bcrypt(plaintext))
- Description
- ExpiresAt         (NULL = no expiration)
- LastUsedAt
- CreatedAt

The full plaintext key is returned to the client only once, when it is created.

Cleanup Policy

- ID
- Name
- Type (cleanup/security)
- Rules
- Repositories
- Enabled
- Created/Updated timestamps

Installation Options

CodeScoring.Save supports several installation profiles. Requirements, profile differences, and deployment steps are described in Installation Options.

Security

Authentication and Authorization

  • JWT tokens for API, issued by Auth/RBAC service
  • Basic Auth / API keys for package managers and service accounts
  • Role-based access control (RBAC) with three scopes (global / project / repository), managed by the dedicated Auth/RBAC service
  • Inter-service token validation through the JWKS endpoint

Client-side authentication methods are described in detail in Authentication.

Data Encryption

Save and cs-auth services do not perform application-level encryption; encryption is provided by the underlying components:

  • Encryption at rest is provided by the selected object storage (S3 server-side encryption, MinIO encryption-at-rest) and PostgreSQL (through TDE extensions or volume-level encryption).
  • Encryption in transit is provided by TLS on ingress / load balancer and in inter-service connections.
  • User passwords and robot account API keys are stored as bcrypt hashes in cs-auth.

Audit

  • Complete logging of all operations into a unified event log used by both services.
  • Export to machine-readable format (JSON) and HTML. A single export can contain up to 10,000 records.
  • Supported filters for list/export: from, to, username, action, resource_type, q, user_id. In the web UI, search is available only by username, resource type, and action.

Performance

Optimizations

  • Caching:
  • In-process TTL cache credential -> PermissionSet in each Save API service pod, removing the round trip to cs-auth for repeated requests with the same credentials.
  • Local Bearer JWT validation through the JWKS public key, without a network call to cs-auth on the hot path. JWKS is refreshed periodically in the background.

  • Connection pooling:

  • Database connection pool.
  • Reused HTTP clients for upstream repositories.

  • Parallel processing:

  • Concurrent uploads / downloads through goroutines.
  • Batch (bulk) operations API.

  • Streaming large files:

  • Artifacts are transferred through MultiWriter without buffering the full file in memory.
  • Atomic disk writes through temp-file rename to avoid corruption during concurrent writes.

Target Metrics

For a basic installation:

  • Latency (p95): < 100 ms for cached requests
  • Throughput: 300+ requests/sec
  • Concurrent uploads: 100+
  • Max artifact size: 5 GB

Scaling

Horizontal Scaling

  • Save API service: stateless, scaled by adding replicas.
  • Auth/RBAC service: stateless, scaled by adding replicas. Required condition: all replicas must share the same RSA key for signing JWT tokens (AUTH_JWT_RSA_KEY_PATH).
  • PostgreSQL: vertical scaling + read replicas if needed.
  • Object storage: scaled horizontally by the provider (S3, MinIO in a cluster).

Vertical Scaling

  • Increasing pod resources.
  • Increasing PostgreSQL capacity.
  • Expanding object storage.

Monitoring and Observability

Metrics (Prometheus)

Save exports metrics in OpenTelemetry format with Prometheus exporter.

HTTP metrics:

  • http_requests_total{method,path,status} — HTTP request counter.
  • http_request_duration_seconds{method,path,status} — latency histogram.
  • http_requests_active — active request gauge.

Operation metrics:

  • storage_operations_total{operation,backend,success} — storage operations.
  • artifact_uploads_total{artifact_type,repository} — artifact uploads.
  • artifact_downloads_total{artifact_type,repository} — artifact downloads.
  • proxy_requests_total{artifact_type,repository,cache_hit,success} — proxy requests. Cache hit rate is calculated as rate(proxy_requests_total{cache_hit="true"}[5m]) / rate(proxy_requests_total[5m]).
  • cleanup_operations_total{policy_type,repository,artifacts_deleted,success} — cleanup operations.

Logging

  • Structured logs in JSON format (or text, depending on configuration).
  • Levels: debug, info, warn, error.
  • Output: stdout, stderr, or file.
  • Compatible with any log aggregator that can process JSON (ELK, Loki, Vector).

Availability and Resilience

CodeScoring.Save does not implement automatic failover, point-in-time recovery, or built-in backup on its own. These capabilities are provided by the standard tools of the infrastructure where the service is deployed:

  • Multiple Save and cs-auth replicas in Kubernetes behind a load balancer provide availability if one pod fails.
  • PostgreSQL replication and database backup are configured through the PostgreSQL operator or managed service.
  • Object storage snapshots and replication are handled by the S3-compatible storage provider.
  • Multi-node Kubernetes cluster provides resilience to node failure.

Save does not lose data on restart because all state is external: metadata is stored in the database and artifacts are stored in object storage. Stateless Save architecture allows scaling and pod recreation without data loss.

Страница была полезна?